likes
comments
collection
share

关于webpack.optimization.splitChunks的心得

作者站长头像
站长
· 阅读数 12

最近在研究webpack打包优化,看到optimization.splitChunks分割chunks的相关配置,研究关于异步和同步chunks做代码分割并提前加载(prefetch和preload)的功能;项目用的是VUE框架,又看了下@vue/cli-service关于webpack的默认配置和关于提前加载(prefetch和preload)那块做的优化处理;之后又碰到了prefetch和preload加载不生效的问题;最后偶然间悟了,原来是....

先过一遍webpack对代码分割功能的实现方式:

  1. 多入口分割:entry
  2. 防止重复:使用 Entry dependencies 或者 SplitChunksPlugin 去重和分离 chunk
  3. 动态导入:使用es module的import方法和wepack独有的require.ensure

咱主要看SplitChunksPlugin 插件

由于webpack4和5对optimization.splitChunks的默认配置不同,我们先看下webpack5:

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async',// 指明要分割的插件类型, async:异步插件(动态导入),inital:同步插件,all:全部类型
      minSize: 20000,// 文件最小大小,单位bite;即超过minSize有可能被分割;
      minRemainingSize: 0,// webpack5新属性,防止0尺寸的chunk
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 30,// webpack4,5区别较大
      maxInitialRequests: 30,// webpack4,5区别较大
      enforceSizeThreshold: 50000,
      cacheGroups: {
        defaultVendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          reuseExistingChunk: true
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};

咱主要看cacheGroups,上面分了两个chunks缓存组,一个用于node_modules下面的chunk,一个用于共享的chunk;

假设我们某个异步chunks是被分割,那么我们怎么怎么使用prefetch和preload来优化页面的加载时间呢?   那就要用到:预获取/预加载模块。

**

贴一下webpack对预获取/预加载模块的官方描述:

**

webpack v4.6.0+ 增加了对预获取和预加载的支持。在声明 import 时,使用下面这些内置指令,可以让 webpack 输出 "resource hint(资源提示)",来告知浏览器:prefetch(预获取):将来某些导航下可能需要的资源preload(预加载):当前导航下可能需要资源

下面是具体怎么使用resource hint来提示浏览器,有人称这些注释为:魔法修饰符😂

//...
import(/* webpackPrefetch: true */ './path/to/LoginModal.js');
//...
import(/* webpackPreload: true */ 'ChartingLibrary');

Q: 为什么我们vue框架中没有使用resource hint,webpack依然生成了预加载和预获取的link标签呢?

答:因为Vue CLI 也会自动注入 resource hint (preload/prefetch、manifest 和图标链接 (当用到 PWA 插件时) 以及构建过程中处理的 JavaScript 和 CSS 文件的资源链接。

@vue/cli-service中引入了@vue/preload-webpack-plugin,默认情况下,一个 Vue CLI 应用会为所有初始化渲染需要的文件自动生成 preload 提示。这些提示会被@vue/preload-webpack-plugin 注入,并且可以通过 chainWebpackconfig.plugin('preload') 进行修改和删除。

原来是框架底层帮我们把所有的初始化渲染用到的问件通过@vue/preload-webpack-plugin自动生成了preload 资源提示;

Q: 有人可能跟我一样,遇到了prefetch加载两次资源且用时一样的情况,那么原因是为什么呢?

这种情况有一种原因,那就是你再用dev-tool调试的时候打开了disable:cache功能,这样子prefetch过的资源会无视缓存重新请求,当你把disable:cache关闭之后,第二次的time用时就会变得非常小,几毫秒,如下:

关于webpack.optimization.splitChunks的心得

Q: 很多人说自己的prefetch和preload不生效

答:那有可能是浏览器的问题,因为这两个功能是html5的新功能,浏览器厂商支持情况不一样,见下图:

关于webpack.optimization.splitChunks的心得

总结:webpack代码分割有多种实现方式,关于SplitChunkPlugin,大家可以看官方文档,里面的参数配置还是挺多的,硬着头皮看吧。还有事关于prefetch和preload的用法和实现,还有兼容性,大家都要有大概的认识,才能很好的结合项目做出更适合的代码打包优化;