1

看了官方文档之后发现splitChunks.chunks可以接收initial、async、all,很困惑这三种分割代码模式的区别,现在我们引入例子来探索一下:

下面有两个脚本文件a.js、b.js,两个文件有一些相同的引入,包括动态加载,我们使用Webpack Bundle Analyzer Plugin插件来分析模块是如何进行拆分的。

1、chunks:'async'优化动态加载模块

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
  entry: {
    a: './code_split_mode/a.js',
    b: './code_split_mode/b.js'
  },
  output: {
    path: path.resolve(__dirname, 'build'), // 打包文件的输出目录
    filename: '[name].bundle.js', // 代码打包后的文件名
    publicPath: __dirname + '/build/', // 引用的路径或者 CDN 地址
    chunkFilename: '[name].js' // 代码拆分后的文件名
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  // 拆分代码配置项
  optimization: {
    splitChunks: {
      cacheGroups: {
        node_vendors: {
          test: /[\\/]node_modules[\\/]/,
          chunks: 'async',
          priority: 1
        }
      }
    }
  },
  plugins: [
    new CleanWebpackPlugin(), // 会删除上次构建的文件,然后重新构建
    new BundleAnalyzerPlugin()
  ]
}

执行效果:
1.png

2.png!

async 模式下的输出

  • a,b 中均同步引入的 jquery 被打包进了各自的 bundle 中没有拆分出来共用,因为这种模式下只会优化动态加载的代码。
  • react 打了两份

    • 一份在a 自己的 bundle 中,因为它同步引入了 react,而我们只优化动态加载的代码,所以这里的 react 不会被优化拆分出去。
    • 一份在单独的文件中,它是从 b 里面拆出来的,因为 b 中动态加载了 react
  • lodash 因为在 a,b 中都是动态加载,形成了单独的 chunka, b 共用。

2、chunks:'initial'优化同步加载模块

webpack.config.js配置中将chunks: 'async'改成'initial'
3.png
initial模式下的输出

initial即原始的拆分,原则就是有共用的情况即发生拆分。动态引入的代码不受影响,它是无论如何都会走拆分逻辑的(毕竟你要动态引入嘛,不拆分成单独的文件怎么动态引入?!)。而对于同步引入的代码,如果有多处都在使用,则拆分出来共用。

  • jquery 在这种模式下发生了变化。形成了单独的 chunka,b 共用。
  • react 没有变,因为它在 a,b 中引用的方式不同,所以不会被当成同一个模块拆分出来共用,而是走各自的打包逻辑。在 a 中同步引用,被打入了 abundle。在 b 中动态引入所以拆分成了单独的文件供 b 使用。
  • lodash 没变,形成单独一份两者共用。

3、chunks:'all'优化同步和动态加载模块

5.png
从上面initial模式下我们似乎看出了问题,即 在 a 中同步引入在 b 中动态引入的 react,它其实可以被抽成文件供两者共用的,只是因为引入方式不同而没有这样做。

所以all这种模式下,就会智能地进行判断以解决这个问题。此时不关心引入的模块是动态方式还是同步方式,只要能正确判断这段代码确实可以安全地进行拆分共用,那就干吧。

需要注意的是这里需要设置minSize以使react能够正确被拆分,因为它小于 30k,在同步方式下,默认不会被拆分出来(联想文章开头提到的那些条件)。

cacheGroups: {
 vendor: {
    chunks: "all",
    test: /[\\/]node_modules[\\/]/,
    minSize: 0,
 }
}

4、结论

看起来似乎all是最好的模式,因为它最大限度地生成了复用的代码,Webpack 默认就走这个模式打包不就得了。

参考链接:
https://github.com/wayou/wayou.github.io/issues/40
https://medium.com/dailyjs/webpack-4-splitchunks-plugin-d9fbbe091fd0


记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。


引用和评论

1 篇内容引用
0 条评论