浅谈React + Webpack 构建打包优化(3)

因此可以将第三库的代码单独拆分成 vendor chunk,与业务代码分离。这样就算业务代码再怎么发生变化,只要第三方库代码没有发生变化,对应的 hash 就不变。

首先 entry 配置两个 app 和 vendor 两个chunk

entry: {
 vendor: [path.join(__dirname, 'dll', 'vendors.js')],
 app: [path.join(__dirname, 'src/index')]
},
output: {
 path: path.resolve(__dirname, 'build'),
 filename: '[name].[chunkhash:8].js'
},

其中 vendros.js 是自己定义的哪些第三方库需要纳入 vendor 中,如下:

require('babel-polyfill');
require('classnames');
require('intl');
require('isomorphic-fetch');
require('react');
require('react-dom');
require('immutable');
require('redux');

然后通过 CommonsChunkPlugin 拆分第三库

plugins.push(
 // 拆分第三方库
 new webpack.optimize.CommonsChunkPlugin({ name: 'vendor' }),
 // 拆分 webpack 自身代码
 new webpack.optimize.CommonsChunkPlugin({
  name: 'runtime',
  minChunks: Infinity
 })
);

上面的配置有两个细节需要注意

  1. 使用 chunkhash 而不用 hash
  2. 单独拆分 webpack 自身代码

使用 chunkhash 而不用 hash

先来看看这二者有何区别:

  1. hash 是 build-specific ,任何一个文件的改动都会导致编译的结果不同,适用于开发阶段
  2. chunkhash 是 chunk-specific ,是根据每个 chunk 的内容计算出的 hash,适用于生产

因此为了保证第三方库不变的情况下,对应的 vendor.js 的 hash 也要保持不变,我们再 output.filename 中采用了 chunkhash

单独拆分 webpack 自身代码

Webpack 有个已知问题:

webpack 自身的 boilerplate 和 manifest 代码可能在每次编译时都会变化。

这导致我们只是在 入口文件 改了一行代码,但编译出的 vendor 和 entry chunk 都变了,因为它们自身都包含这部分代码。

这是不合理的,因为实际上我们的第三方库的代码没变,vendor 不应该在我们业务代码变化时发生变化。

因此我们需要将 webpack 这部分代码分离抽离

new webpack.optimize.CommonsChunkPlugin({
   name: "runtime",
   minChunks: Infinity
}),

其中的 name 只要不在 entry 即可,通常使用 "runtime" 或 "manifest" 。

另外一个参数 minChunks 表示:在传入公共chunk(commons chunk) 之前所需要包含的最少数量的 chunks。数量必须大于等于2,或者少于等于 chunks的数量,传入 Infinity 会马上生成 公共chunk,但里面没有模块。

更多关于 CommonChunkPlugin 可以查看 官方文档

拆分公共资源

同 上面的拆分第三方库一样,拆分公共资源可以将公用的模块单独打出一个 chunk,你可以设置 minChunk 来选择是共用多少次模块才将它们抽离。配置如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/93.html