加载速度优化专项 > 体积优化分享
说到加载速度优化我们能想到什么?网上能找到一些什么内容?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 真的是救星嘛?一般情况下是的,支持多路复用(突破六个链接限制,比如说有慢接口,大文件),头部压缩。
- 有线 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编码的方法
4.合理的 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
这个主要是分析代码执行效率的。