作用
虽然webpack4已经出来很久了,CommonsChunkPlugin也已经舍弃了,但是还是有很多项目是通过webpack3来打包的,对CommonsChunkPlugin各个配置项的认识还是比较模糊,这里做个详细的记录。

CommonsChunkPlugin通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,以便存到缓存中供后续使用。

    既然是将公共模块拆分出来,那么肯定是要有多个被打包的模块,即公共模块的来源,包括 入口文件和 已近提取出来的公共模块,如果来源只有一个,那么就立即被打包成一个单独文件,不会抽取公共模块,因为一个chunk来源是不会出现公共模块的,这是webpack打包策略,只会出现各个组件的相互引用,这种情况用于提取第三方库等;如果来源很多个,那么会提取出公共的模块组成一个单独的文件,来源文件再各自打包成各自的单独文件
    这里最重要的是搞清楚的就是配置项中各种chunk的概念和来源,我们首先看看有哪些配置选项。再对配置项逐一解析。

用法

  1. new webpack.optimize.CommonsChunkPlugin(options);

options选项及官方翻译

  1. {
  2.   name: string, // or
  3.   names: string[],
  4.   /*name或者names是入口文件中的chunk名称,公共模块chunk可以在入口文件中定义名称和所对应的模块,然后被选择;
  5.   *name和names的不同在于:name只选择一个入口chunk进行分开打包,names相当于name的遍历版,
  6.   *对names数组中的chunk遍历,然后单独打包,此时options.filename不能是具体的名称,某则会出现相同的名称而报错,
  7.   * */
  8.   // 如果该选项被忽略,同时 `options.async` 或者 `options.children` 被设置,所有的 chunk 都会被使用,
  9.   // 否则 `options.filename` 会用于作为 chunk 名。
  10.  
  11.   filename: string,
  12.   /*文件的名字模板,可以使用和output相同的占位符,如[hash:7],7代表7位hash符号,默认是20位;
  13.   * 默认名字与`output.filename` 或者 `output.chunkFilename`相同*/
  14.  
  15.   minChunks: number|Infinity|function(module, count) => boolean,
  16.   // 在传入 公共chunk(commons chunk) 之前所需要包含的最少数量的 chunks 。
  17.   // 数量必须大于等于2,或者少于等于 chunks的数量
  18.   // 传入 `Infinity` 会马上生成 公共chunk,但里面没有模块。
  19.   // 你可以传入一个 `function` ,以添加定制的逻辑(默认是 chunk 的数量)
  20.   /*module.context代表chunk所以在的文件夹路劲,
  21.   *module.resource代表该chunk的文件路劲
  22.   *count chunk被引入的次数*/
  23.  
  24.   chunks: string[],
  25.   // 通过 chunk name 去选择 chunks 的来源。chunk 必须是 公共chunk 的子模块。
  26.   // 如果被忽略,所有的,所有的 入口chunk (entry chunk) 都会被选择。
  27.   /*chunks和children是相同的作用,不同的是chunks只选择特定的子模块抽取公共模块,
  28.   *而children是选择所有的子模块*/
  29.  
  30.   children: boolean,
  31.   // 如果设置为 `true`,所有公共 chunk 的子模块都会被选择
  32.   /*将子模块的公共模块打包进父 chunk */
  33.  
  34.   deepChildren: boolean,
  35.   // 如果设置为 `true`,所有公共 chunk 的后代(子孙)模块都会被选择
  36.  
  37.   async: boolean|string,
  38.   // 如果设置为 `true`,一个异步的 公共chunk 会作为 `options.name` 的子模块,和 `options.chunks` 的兄弟模块被创建。
  39.   // 它会与 `options.chunks` 并行被加载。
  40.  
  41.   minSize: number,
  42.   // 在 公共chunk 被创建立之前,所有 公共模块 (common module) 的最少大小。
  43. }

配置项介绍
不按照上面的顺序介绍,有些配置项很相似,容易弄混,按照我自己理解来解释。

1. filename
这是文件名的模板,和output.filename 或者 output.chunkFilename是一个意思,最终生成的文件名。

如果配置了这个项,以这个模板优先取名,否则,按照output.filename 或者 output.chunkFilename规则取名。

2. name or names
这个抽取的公共模块的名字,这个和filename还是有区别的,filename=name+hash+其它可能的配置项+ext。
example1: 这里adminA和adminB都引入的common.js,所以会抽取common.js作为公共模块。

  1. //adminA
  2. require("./common")
  3. console.log("adminA")
  1. //adminA
  2. require("./common")
  3. console.log("adminB")
  1. entry: {
  2.   adminA: "./adminA",
  3.   adminB: "./adminB",
  4. },
  5. output: {
  6.   path: path.join(__dirname, "dist"),
  7.   filename: "[name].js"
  8. },
  9. plugins: [
  10.   new webpack.optimize.CommonsChunkPlugin({
  11.     name: "commons",
  12.   }),
  13. ]

打包生成名为 commons的公共模块

同时,如果这个name和入口文件的name相同,那么入口文件直接被选择为打包来源,即直接指定name所指定的入口文件为公共模块;这个在很明确公共模块是什么的时候很有用,比如第三方库,可以直接指定。
names则是通过遍历names数组,执行多次该插件,免去写多个相同的代码(如果有这个需求)。例:
example2: 增加adminC,但是没有引入common.js,只有adminA和adminB引入了。

  1. //adminC
  2. console.log("adminC");
  1. entry: {
  2.   adminA: "./adminA",
  3.   adminB: "./adminB",
  4.   adminC: "./adminC",
  5. },
  6. output: {
  7.   path: path.join(__dirname, "dist"),
  8.   filename: "[name].js"
  9. },
  10. plugins: [
  11.   new BundleAnalyzerPlugin(),
  12.   new webpack.optimize.CommonsChunkPlugin({
  13.     name: "commons",
  14.   }),
  15. ]

虽然也生成了commons.js但是其实里面没有任何东西(文件很小),adminA和adminB文件还是很大,也就是没有抽取公共模块:

可以用插件webpack-bundle-analyzer分析:common.js还是存在adminA.js和adminB.js里面

这个时候在入口文件直接指定公共模块commons:
example3

  1. entry: {
  2. adminA: "./adminA",
  3. adminB: "./adminB",
  4. adminC: "./adminC",
  5. //name和配置项的name相同
  6. commons: './common.js'
  7. },

可以从文件大小看出来,公共模块已经抽取出来了。

3. minChunks
被其他模块引用的次数 (默认是3),只有满足这个引入次数条件才会被抽取,如果设置成 Infinity (无限大,不可能满足),那么会立即打包成一个独立模块,不会抽取公共模块,用于公共模块很明确的时候或者想直接打包某一chunk。

例如前面的example2,也可以不用在入口指定公共模块,主要是因为minChunk的默认值是3,而common.js只被adminA和adminB引入了,也就是只引入了两次,所以不会被打包,我们这里将example2的minChunks设置2,再打包:
example4:

  1. entry: {
  2.   adminA: "./adminA",
  3.   adminB: "./adminB",
  4.   adminC: "./adminC",
  5. },
  6. output: {
  7.   path: path.join(__dirname, "dist"),
  8.   filename: "[name].js"
  9. },
  10. plugins: [
  11.   new BundleAnalyzerPlugin(),
  12.   new webpack.optimize.CommonsChunkPlugin({
  13.     name: "commons",
  14.     minChunks: 2
  15.   }),
  16. ]

从文件大小上可以看出,common.js已经抽取出来了:

minChunks也可以是一个函数,webpack会遍历所有来源chunk,逐一执行这个函数,函数返回true这个chunk才被提取为公共模块。这个函数用于更加精确的提取公共模块,如vue构建工具生成的配置文件,可以提取所有在文件夹node_modules中的模块:
example5:

  1. //这里是提取所有的第三方插件,如我这里有vue,vue-router,echarts
  2. //但是echarts太庞大了,需要和vue,vuer-router分离
  3. new webpack.optimize.CommonsChunkPlugin({
  4.   name: 'vendor',
  5.   minChunks(module) {
  6.     /*module.context代表chunk所以在的文件夹路劲,
  7.     *module.resource代表该chunk的文件路劲
  8.     *count chunk被引入的次数*/
  9.     return (
  10.       module.resource &&
  11.       /\.js$/.test(module.resource) &&
  12.       module.resource.indexOf(
  13.         path.join(__dirname, '../node_modules')
  14.       ) === 0
  15.     )
  16.   },
  17.   chunks: ["app"]
  18. }),
  19. //分离vue,vue-router,echarts是按需引入的,不太方便按这种方式抽取。
  20. new webpack.optimize.CommonsChunkPlugin({
  21.   name: 'vue',
  22.   minChunks: function (module) {
  23.     return (module.resource && /\.js$/.test(module.resource) && (/vue/).test(module.resource))
  24.   },
  25.   chunks: ['vendor']
  26. }),

4. chunks

选择chunk来源,即选择要被抽取的模块来源,这个很好理解,即被选择的chunk来源才会被抽取公共模块。如:A和B同时引入C,而D没有引入C,那么就可以只选择A和B作为chunk来源,抽取A、B的公共模块C,否则C可能不会被抽取为公共模块。
eample6: adminA、adminB和adminC都引入common.js,但是chunks只选择adminA和B。

  1. entry: {
  2.   adminA: "./adminA",
  3.   adminB: "./adminB",
  4.   adminC: "./adminC",
  5. },
  6. output: {
  7.   path: path.join(__dirname, "dist"),
  8.   filename: "[name].js"
  9. },
  10. plugins: [
  11.   new BundleAnalyzerPlugin(),
  12.   new webpack.optimize.CommonsChunkPlugin({
  13.     name: "commons",
  14.     minChunks: 2,
  15.     chunks: ['adminA', 'adminB']
  16.   }),
  17. ]

结果:adminA和adminB的common.js被抽取出来了,但是adminC的common.js没有被抽取出来(从大小上判断)。

5. children
children: webpack官方给出了一个案例,中文版是翻译过来的,但是我看了很久都没看明白,其实翻译是不够严谨的,案例中翻译说 一个 chunk的子模块会有公共模块,配置参数里面翻译是公共模块的子模块会有公共依赖,我想了好久,都没想出这个子模块是什么意思;其实是 一个入口的模块的子模块,子模块指的是 异步加载模块、通过代码分割功能从这个入口chunk分离出来的chunk,在模块中使用import()或者require.ensure(),会单独打包这一部分模块。

eample7: adminA通过代码分割功能,异步加载childA和childB,childA和childB都引入了jquery和common。

  1. //adminA.js
  2. import('./childA');
  3. import('./childB');
  4. console.log("adminA");
  1. //chuildA
  2. import './jquery';
  3. import './common';
  4. console.log('childA');
  1. //chuildB
  2. import './jquery';
  3. import './common';
  4. console.log('childB');
  1. //webpack.config.js
  2.  
  3. entry: {
  4.   adminA: "./adminA",
  5. },
  6. output: {
  7.   path: path.join(__dirname, "dist"),
  8.   filename: "[name].js",
  9.   chunkFilename: '[name].chunk.js'
  10. },
  11. plugins: []

不优化的打包结果:生成了两个异步的chunk,0和1,就是childA和childB。childA和childB都引入了common.js和jquery.js,体积很大。

我们试着优化,看能不能把异步加载的模块的公共模块抽取出来:
eample8:

  1. //webpack.config.js
  2. entry: {
  3.   adminA: "./adminA",
  4. },
  5. output: {
  6.   path: path.join(__dirname, "dist"),
  7.   filename: "[name].js",
  8.   chunkFilename: '[name].chunk.js'
  9. },
  10. plugins: [
  11.   new webpack.optimize.CommonsChunkPlugin({
  12.     name: "commons",
  13.     minChunks: 2
  14.   }),
    ]

结果:common.js和jquery.js并没有抽取出来成为公共模块,只是抽取了webpack代码分离功能的代码,因为代码分离出来的chunk,并不在chunk来源选择范围内(忽略了chunks选项,那么默认是全部的chunk来源,但是排除代码分离的chunk)。

我们加上children:true,并且需要把name设置成入口chunk的name,此处是adminA:

eample9:

  1. //webpack.config.js
  2. entry: {
  3.   adminA: "./adminA",
  4. },
  5. output: {
  6.   path: path.join(__dirname, "dist"),
  7.   filename: "[name].js",
  8.   chunkFilename: '[name].chunk.js'
  9. },
  10. plugins: [
  11.   new webpack.optimize.CommonsChunkPlugin({
  12.     name: "adminA",
  13.     minChunks: 2,
  14.     children: true
  15.   }),
    ]

结果:common.js和jquery.js被打包进了adminA,也就是代码分离后子模块的公共模块被打包进了父模块。减少了总体体积。但是会增加初始加载时间(即加载adminA的时间会延长),如果分离子模块的公共代码很多,并且预计到用户会加载很多子模块(代码分离的子模块),可以这样做。当然,还有另外一种方法,就是async.

6.async

async: 就是把代码分离模块的公共模块抽取出来。不同于上面children:true是把公共模块抽取放到父模块中,async:true把公共模块单独抽取出来作为一个公共模块,和之前抽取公共模块是一样的,只不过这个抽取的是分离代码的公共模块。

再看**example10:**在example9的基础上加上async,async可以取值Boolean值也可以是string,如果是string,那么这个string值作为chunk打包后的name,如果是Boolean值,那么打包后的name就是0。

同样,这里的options.name要和入口chunk的name匹配

  1. entry: {
  2.   adminA: "./adminA",
  3. },
  4. output: {
  5.   path: path.join(__dirname, "dist"),
  6.   filename: "[name].js",
  7.   chunkFilename: '[name].chunk.js'
  8. },
  9. plugins: [
  10.   new BundleAnalyzerPlugin(),
  11.   new webpack.optimize.CommonsChunkPlugin({
  12.     //要和入口chunk的name匹配
  13.     name: "adminA",
  14.     minChunks: 2,
  15.     children: true,
  16.     async: "async-chunk"
  17.   }),
  18. ]

名为async-chunk.chunk.js就是我们分离代码的公共模块。

7.minSize
抽取公共代码之前,应该满足的文件的大小。如果抽取出来的公共代码文件大小只有几kb,这样会增加请求次数,还不如不抽取。

8.deepChildren
这个目前还不知道有什么用,和children差不多,children选择的是直接子代,deepChildren选择的是所有后代,但是目前我并没有发现它有什么用。

原文链接:https://blog.csdn.net/zy444263/article/details/85252477

[转]webpack——CommonsChunkPlugin的更多相关文章

  1. webpack CommonsChunkPlugin详细教程

    1.demo结构: 2.package.json配置: { "name": "webpack-simple-demo", "version" ...

  2. [Webpack 2] Chunking common modules from multiple apps with the Webpack CommonsChunkPlugin

    If you have a multi-page application (as opposed to a single page app), you’re likely sharing module ...

  3. [Webpack 2] Grouping vendor files with the Webpack CommonsChunkPlugin

    Often, you have dependencies which you rarely change. In these cases, you can leverage the CommonsCh ...

  4. webpack CommonsChunkPlugin 提取公共代码

    1.项目结构 2.部分代码 module.js console.log('module.js'); index文件夹下的index.js require('../module.js'); consol ...

  5. Webpack+React+ES6开发模式入门指南

    React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了Reac ...

  6. Webpack+React+ES6入门指南[转]

    React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了Reac ...

  7. webpack 多页应用架构系列实战

    阅读目录 1.webpack配置了解 2.webpack CommonsChunkPlugin公共代码剥离 3.了解ProvidePlugin的用途 回到顶部 1.webpack配置了解 webpac ...

  8. React的React Native

    React的React Native React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React ...

  9. 关于webpack.optimize.CommonsChunkPlugin的使用二

    Note:当有多个入口节点的时候,只有所有入口节点都引入了同一个模块的时候,webpack.optimize.CommonsChunkPlugin才会将那个模块提取出来,如果其中一个入口节点没有引入该 ...

随机推荐

  1. 企业级BI是自研还是采购?

    企业级BI是自研还是采购? 上一篇<企业级BI为什么这么难做?>,谈到了企业级BI项目所具有的特殊背景,以及在"破局"方面的一点思考,其中谈论的焦点主要是在IT开发项目 ...

  2. Redis学习推荐资料合集

    目录 一.官方 二.书籍 三.推荐博客 一.官方 redis官网 redis中文网 redis中文命令网 redis模块 redis-github源码 redis报告 二.书籍 <Redis开发 ...

  3. <转>C/S架构分析

    系统架构师-基础到企业应用架构-客户端/服务器 开篇 上篇,我们介绍了,单机软件的架构,其实不管什么软件系统,都是为了解决实际中的一些问题,软件上为了更好的解决实际的问题才会产生,那么对于单机软 件的 ...

  4. 学习型的“文山表海无限发展公司”——《Office妖精是怎样炼成的》续1

    本篇无故事情节版:https://www.cnblogs.com/officeplayer/p/14841590.html <Office妖精是怎样炼成的>http://blog.sina ...

  5. 小迪安全 Web安全 基础入门 第六天 - 信息打点-Web架构篇&域名&语言&中间件&数据库&系统&源码获取

    一 . Web架构 语言.常用的Web开发语言有PHP,Java,Python,JavaScript,.net等.具体可参考w3school的介绍. 中间件. (1)常见的Web服务器中间件:IIS. ...

  6. 小迪安全 Web安全 基础入门 - 第四天 - 30余种加密编码进制&Web&数据库&系统&代码&参数值

    一.密码存储加密 1.MD5值是32或16位由数字"0-9"和字母"a-f"所组成的字符串 2.SHA1加密的密文特征与MD5类似,但位数是40位 3.NTLM ...

  7. 一篇文章讲明白vue3的script setup,拥抱组合式API!

    引言 vue3除了Composition API是一个亮点之外,尤大大又给我们带来了一个全新的玩意 -- script setup,对于setup大家相信都不陌生,而对于script setup有些同 ...

  8. Linux(centos7)安装redis并设置redis开机自启动

    1.下载redis安装包 wget http://download.redis.io/releases/redis-4.0.6.tar.gz 2.解压安装包 tar -zxvf redis-4.0.6 ...

  9. js中的jQuery Validate增加手机号码验证

    $.validator.addMethod("isPhone", function(value,element) { var length = value.length; var ...

  10. win10+vs2015编译nanogui

    !!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!! 作者:mohist 说明: A.OS : win10 1909 ,没有配置OpenGL开发环境的 经历. B. ...