5
头图

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

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

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

网络、加载速度优化

  1. 为什么我说 CDN 可以提速不全对?脱离剂量谈毒性,都是耍流氓(这里指脱离环境一把梭哈不现实)
    CDN 是指是什么?

    CDN 的全称是 Content Delivery Network,即内容分发网络。CDN 是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。
    1. 如果你的 CDN 本身节点比较少,并没有覆盖全面,那么并不会提速。(比如说你买的这个 CDN 没有海外节点,但是你想提升海外节点的访问速度)
    2. 如果你的 CDN 是外网的,而你的项目是内网,那么速度反而会更慢。(内网的距离比较近,所以速度快,内网带宽足,所以速度快)
    3. 你的 CDN 是否可以承载你的请求量级?(比如说目前各大厂子都在自研自己的云服务,阿里云、腾讯云)
  2. 开启 GZIP 真的提速了吗?是的真的提速了。但是一般服务器早都开启了。
    是没有损耗的嘛?有损耗每个文件都会计算 gzip,且无缓存。可以手动生成对应的 gz 文件。
  3. 开启缓存?无脑缓存?看来你是没有被 ios 支配过。
    一般来说缓存也都是开启状态。我们目前一般的方案是 html 文件无缓存,js、css 强缓存 hash 控制。
  4. HTTP2 真的是救星嘛?一般情况下是的,支持多路复用(突破六个链接限制,比如说有慢接口,大文件),头部压缩。
    但是在高延迟的情况下,HTTP2 反而会更慢
  5. 有线 vs 无线(WIFI、4G),服务商对于网络有影响嘛?只有外网项目受影响嘛?

    1. 外网。服务商对于网络是有影响的,比如我家就是移动,ping 部分 ip 丢包严重,光纤和 4G 都是如此。使用联通 4G 就什么问题都没有。
    2. 内网。这里推荐使用有线,比较稳定。这里分为两个场景:

      1. 公司,一般都是 AP 面板。但是有时候 AP 节点就是换不过来,偶尔网络波动。再看 P90 的数据的时候就特别难看。
      2. 家里,一般都是单个路由器。你可以参考在信号强时,和信号弱时比对加载速度。

体积优化

  1. Tree-shaking。好像有了 Tree-shaking 就完事大吉了。

    1. 但是在 webpack4 以后就是默认开启的了。(yarn serve 不优化, yarn build 优化,内部通过环境变量控制的)
    2. Tree-shaking 只对 ES Module 起作用,对于 commonjs 无效,对于 umd 亦无效。
    3. 如果你的三方包不支持,那么就不支持。所以这里需要更新你包的版本,支持 按需 和 tree-shaking
  2. 依赖共享。

    1. 比如说我们写了一个 Request 库,里面用了 axios。然后我们还有个消息中心的库,里面也用了 axios。这个时候输出的包里面会有两个 axios。
      这里我们用的是(monorepo Lerna yarn)+ (config.externals)实现依赖共享,只载入一份 axios。
    2. 还有一个情况是我们使用了按需组件库。但是主项目并没有按需,而是全量导入,导致载入了两遍 element-ui。解决办法就是主项目改成全量按需。

      [
       'component',
       {
       "libraryName": "element-ui",
       "styleLibraryName": "theme-chalk"
       },
       'element-ui',
      ],
  3. 分包。 对于不需要的资源延时加载、异步加载。比如说有个流程中心,在你审批的时候同步加载了几千个流程。但是你只需要使用其中一个。

    1. 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')
      )
    2. 对于大依赖( 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);
              });
          }
      }
    3. 合包。也不能拆太细,平白提高了 QPS。

      1. 什么叫压缩?说白了就是相同和合并,比如说 '11111111111111111111' 改成 '1'.repeat(20)

        内容压缩很简单,它就是移除多余的空白字符,插入单个的重复字符指出一个字符串中重复的字符,以及将小型的位串用频繁使用的字符替代。这种类型的压缩能够将文本文件的大小减少50%。压缩由使用特定公式和算法的程序来执行,它确定如何压缩和解压数据。
        gzip 使用deflate算法进行压缩。gzip 对于要压缩的文件,首先使用LZ77算法的一个变种进行压缩,对得到的结果再使用Huffman编码的方法
  4. 合理的 babel 处理。比如说你的内网项目,那么可以只支持较高版本的浏览器,减少 babel 和 polyfill。

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

逻辑优化

减少串行代码。

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

总结

优化之路,相辅相成。

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

项目实战

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

比如说:
image.png

分析手段

Chrome DevTools Lighthouse

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

  1. 我们看看思否首页,这分就挺高了。不过他们这个是静态直出肯定会好很多,一般慢的都是后台中台 vue、react、单页应用、巨石应用。
    image.png
  2. 我们再看看掘金首页,这个分就差点事了,可以看到有一些优化建议。看了好像他们首页数据好像是骨架,然后后面回来的数据。
    image.png
  3. 之前听说 26 分,我也来看看。image.png

Chrome DevTools Network

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

yarn build --report

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

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

image.png

Chrome DevTools Performance

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


linong
29.2k 声望9.5k 粉丝

Read-Search-Ask