美文网首页
vue-cli中的CommonsChunkPlugin都做了些啥

vue-cli中的CommonsChunkPlugin都做了些啥

作者: btfrankenstein | 来源:发表于2017-10-31 15:51 被阅读0次

    vue-cli中的CommonsChunkPlugin

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

    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都做了些啥

          本文链接:https://www.haomeiwen.com/subject/ktmbpxtx.html