vue-cli中的CommonsChunkPlugin都做了些啥

vue-cli中的CommonsChunkPlugin

下图是使用 vue-cli 构建之后,webpack.prod.conf.js 中有关 CommonsChunkPlugin 的代码块。可以看到 new 了两次 CommonsChunkPlugin。为什么要 new 两次呢?这两次的作用分别是什么呢?

vue-cli中的CommonsChunkPlugin都做了些啥_第1张图片
Jietu20171031-133902.jpg

第一次 new webpack.optimize.CommonsChunkPlugin

webpack 官网对 CommonsChunkPlugin 配置项的解释

{
  name: string,
  // common chunk的名称

  minChunks: number|Infinity|function(module, count){},
  // 官方翻译是在传入公共chunk(commons chunk) 之前所需要包含的最少数量的chunks
  // 个人理解如果 `number` = 3, 说明被加入到common chunks里的模块要至少被三个chunk或者entries共享
  // 传入 `Infinity` 会马上生成 公共chunk,但里面没有模块。
  // 可以传入函数,定制自己的逻辑
}

vue-cli 里的 minChunks 使用的是函数模式,那这个函数又代表了什么呢?继续看官网解释。

调用的函数会传入 modulecount 参数。module 参数代表每个 chunk 里的模块。module 拥有和 NormalModule 类似的特性, 它有两个很有用的属性:

  • module.context : 保存这个模块的目录. 比如: '/my_project/node_modules/example-dependency'
  • module.resource : 模块真正执行的文件名. 比如: '/my_project/node_modules/example-dependency/index.js'

count 参数表示 module 被使用的 chunk 数量。

接下来看 webpack 配置文件中的第一个 new

// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function (module, count) {
  // any required modules inside node_modules are extracted to vendor
  // 翻译注释:所有被依赖的模块,如果它在node_modules目录中,都会被抽离出来放进 vendor.js 中
  // 如果模块有一个路径,而且在路径中有 js 文件,并且这个模块是属于 node_modules 中的模块
  // 那这个模块就会被抽离出来,放进名为 vendor 的这个chunk
    return (
      module.resource &&
      /\.js$/.test(module.resource) &&
      module.resource.indexOf(
        path.join(__dirname, '../node_modules')
      ) === 0
    )
  }
}),

这里,对于 minChunks 传入函数的解释是,如果依赖模块包含路径,而且在路径中有 js 文件,并且这个路径是属于 node_modules 目录的,那这个模块就会被抽离出来,放进名为 vendor 的这个 chunk。也就是说所有在 package.json 里面依赖的包,都会被打包进 vendor.js 这个文件中

这样,就可以把依赖的包代码和我们的业务代码分开。如果依赖包不变,每次我们改变业务代码,在构建的时候就不用改变 vendor 里面的内容。浏览器就可以继续使用上一次的缓存。提高加载速度(当然最后打包出来的 chunk 的文件名都是带 hash 的,所以 vendor chunk 最终的文件名会是 vendor.[chunkhash].js )。

第二次 new webpack.optimize.CommonsChunkPlugin

webpackissue 中有一个讨论 #1315。出现的问题是,当只改变业务代码之后打包,不仅 app.[chunkhash].js 的文件名的 chunkhash 变了(业务代码打包进 app.[chunkhash].js ),vendor.[chunkhash].jshash 同样也改变了。这样缓存机制就失去了意义。所以第二次的 new 就是为了解决这个问题的。

会出现这个问题的根本原因是 webpack 在同时使用 [chunkhash] 和代码分割功能的时候会生成 webpackruntime 代码(它主要用来处理代码模块的映射关系),这意味着 [chunkhash] 每次构建都会改变。解决方案就是把这部分的 runtime 代码单独抽离出来生成单独的 chunk。通过给 CommonsChunkPlugin 传入多个名称来达到这个目的。

// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest',
  chunks: ['vendor']
}),

你可能感兴趣的:(vue-cli中的CommonsChunkPlugin都做了些啥)