Web 页面优化专项 > 加载速度优化专项 > 体积优化


思否
性能优化 HTTP Vue 构建工具 Element UI

转载自 SegmentFault

加载速度优化专项 > 体积优化分享

说到加载速度优化我们能想到什么?网上能找到一些什么内容?CDN? GZIP? 开启缓存?HTTP2? Tree-shaking?

这些内容对吗?不全对!接下来我们针对性的分析一下。

网络、加载速度优化

为什么我说 CDN 可以提速不全对?脱离剂量谈毒性,都是耍流氓(这里指脱离环境一把梭哈不现实) CDN 是指是什么? CDN 的全称是 Content Delivery Network,即内容分发网络。CDN 是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。如果你的 CDN 本身节点比较少,并没有覆盖全面,那么并不会提速。(比如说你买的这个 CDN 没有海外节点,但是你想提升海外节点的访问速度)

  • 如果你的 CDN 是外网的,而你的项目是内网,那么速度反而会更慢。(内网的距离比较近,所以速度快,内网带宽足,所以速度快)
  • 你的 CDN 是否可以承载你的请求量级?(比如说目前各大厂子都在自研自己的云服务,阿里云、腾讯云)
  • 开启 GZIP 真的提速了吗?是的真的提速了。但是一般服务器早都开启了。 是没有损耗的嘛?有损耗每个文件都会计算 gzip,且无缓存。可以手动生成对应的 gz 文件。
  • 开启缓存?无脑缓存?看来你是没有被 ios 支配过。 一般来说缓存也都是开启状态。我们目前一般的方案是 html 文件无缓存,js、css 强缓存 hash 控制。
  • HTTP2 真的是救星嘛?一般情况下是的,支持多路复用(突破六个链接限制,比如说有慢接口,大文件),头部压缩。 但是在高延迟的情况下,HTTP2 反而会更慢

有线 vs 无线(WIFI、4G),服务商对于网络有影响嘛?只有外网项目受影响嘛? 外网。服务商对于网络是有影响的,比如我家就是移动,ping 部分 ip 丢包严重,光纤和 4G 都是如此。使用联通 4G 就什么问题都没有。

内网。这里推荐使用有线,比较稳定。这里分为两个场景: 公司,一般都是 AP 面板。但是有时候 AP 节点就是换不过来,偶尔网络波动。再看 P90 的数据的时候就特别难看。

  • 家里,一般都是单个路由器。你可以参考在信号强时,和信号弱时比对加载速度。

体积优化

Tree-shaking。好像有了 Tree-shaking 就完事大吉了。 但是在 webpack4 以后就是默认开启的了。(yarn serve 不优化, yarn build 优化,内部通过环境变量控制的)

  • Tree-shaking 只对 ES Module 起作用,对于 commonjs 无效,对于 umd 亦无效。
  • 如果你的三方包不支持,那么就不支持。所以这里需要更新你包的版本,支持 按需 和 tree-shaking

依赖共享。 比如说我们写了一个 Request 库,里面用了 axios。然后我们还有个消息中心的库,里面也用了 axios。这个时候输出的包里面会有两个 axios。 这里我们用的是(monorepo Lerna yarn)+ (config.externals)实现依赖共享,只载入一份 axios。

还有一个情况是我们使用了按需组件库。但是主项目并没有按需,而是全量导入,导致载入了两遍 element-ui。解决办法就是主项目改成全量按需。

[
 'component',
 {
 "libraryName": "element-ui",
 "styleLibraryName": "theme-chalk"
 },
 'element-ui',
],

分包。 对于不需要的资源延时加载、异步加载。比如说有个流程中心,在你审批的时候同步加载了几千个流程。但是你只需要使用其中一个。

vue 组件支持异步载入。当组件真的渲染的时候再去加载。

Vue.component('async-example', function (resolve, reject) {
    setTimeout(function () {
        // 向 `resolve` 回调传递组件定义
        resolve({
            template: '<div>I am async!</div>'
        })
    }, 1000)
})
Vue.component(
    'async-webpack-example',
    // 这个动态导入会返回一个 `Promise` 对象。
    () => import('./my-async-component')
)

对于大依赖( xlsx.js、echarts)或者其他不着急的资源也可以异步加载

injectFn() {
    if (this.injected) {return;}
    this.injected = true;
    if (this.useBuiltIn && this.username && this.Prop) {
        import('../../../inject.js').then(({ inject }) => {
            inject(this.Prop!, this.username);
        });
    }
}

合包。也不能拆太细,平白提高了 QPS。

什么叫压缩?说白了就是相同和合并,比如说 ‘11111111111111111111’ 改成 ‘1’.repeat(20) 内容压缩很简单,它就是移除多余的空白字符,插入单个的重复字符指出一个字符串中重复的字符,以及将小型的位串用频繁使用的字符替代。这种类型的压缩能够将文本文件的大小减少50%。压缩由使用特定公式和算法的程序来执行,它确定如何压缩和解压数据。 gzip 使用deflate算法进行压缩。gzip 对于要压缩的文件,首先使用LZ77算法的一个变种进行压缩,对得到的结果再使用Huffman编码的方法

合理的 babel 处理。比如说你的内网项目,那么可以只支持较高版本的浏览器,减少 babel 和 polyfill。

# 你知道这代表了什么?
> 1%
last 2 versions # 表示将会支持 IE10 & IE11

逻辑优化

减少串行代码。

  • Promise.all 代替 axios().then(() => axios())
  • axios1 = axios();axios2 = axios();await Promise.all(axios1,axios2); 代替 await axios();await axios();

总结

优化之路,相辅相成。

  • 优化网络,可以更快加载,也就可以更快执行。
  • 优化并发不阻塞,并行加载,也可以更快执行。
  • 优化体积,更小的体积,更高的复用,这样就可以使用更少的带宽,同样可以更快的执行
  • 使用缓存,更低的 QPS,提前做 DNS 解析。也可以让加载更快。

项目实战

我提供了一些最简案例在仓库中:Demo 仓库地址,你只需要看例子就可以直接看到问题(然后你可以去优化它)。

比如说:

分析手段

Chrome DevTools Lighthouse

这里可以给我们的页面打分,也会给出优化建议。如果能把这里的点都优化了,那么你的页面加载就会起飞。

  • 我们看看思否首页,这分就挺高了。不过他们这个是静态直出肯定会好很多,一般慢的都是后台中台 vue、react、单页应用、巨石应用。

  • 我们再看看掘金首页,这个分就差点事了,可以看到有一些优化建议。看了好像他们首页数据好像是骨架,然后后面回来的数据。

  • 之前听说 26 分,我也来看看。

Chrome DevTools Network

这里主要是看网络阻塞情况,比如说 http1.1 的时候是不是那个请求阻塞了你。

yarn build --report

这个主要是分析包体积的,我使用的工具也主要是这个。

比如说这个案例,你可以看到有多个 axios,然后每一个 axios 那哪里引入的,这个时候你可以考虑通过 peerDependencies 还是 externals 来处理一下这样的资源。

Chrome DevTools Performance

这个主要是分析代码执行效率的。


原文:SegmentFault

评论

评论功能即将开放。你也可以通过 邮件GitHub Issue 反馈。