[转]webpack——CommonsChunkPlugin
作用
虽然webpack4已经出来很久了,CommonsChunkPlugin也已经舍弃了,但是还是有很多项目是通过webpack3来打包的,对CommonsChunkPlugin各个配置项的认识还是比较模糊,这里做个详细的记录。
CommonsChunkPlugin通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,以便存到缓存中供后续使用。
既然是将公共模块拆分出来,那么肯定是要有多个被打包的模块,即公共模块的来源,包括 入口文件和 已近提取出来的公共模块,如果来源只有一个,那么就立即被打包成一个单独文件,不会抽取公共模块,因为一个chunk来源是不会出现公共模块的,这是webpack打包策略,只会出现各个组件的相互引用,这种情况用于提取第三方库等;如果来源很多个,那么会提取出公共的模块组成一个单独的文件,来源文件再各自打包成各自的单独文件
这里最重要的是搞清楚的就是配置项中各种chunk的概念和来源,我们首先看看有哪些配置选项。再对配置项逐一解析。
用法
- new webpack.optimize.CommonsChunkPlugin(options);
options选项及官方翻译
- {
- name: string, // or
- names: string[],
- /*name或者names是入口文件中的chunk名称,公共模块chunk可以在入口文件中定义名称和所对应的模块,然后被选择;
- *name和names的不同在于:name只选择一个入口chunk进行分开打包,names相当于name的遍历版,
- *对names数组中的chunk遍历,然后单独打包,此时options.filename不能是具体的名称,某则会出现相同的名称而报错,
- * */
- // 如果该选项被忽略,同时 `options.async` 或者 `options.children` 被设置,所有的 chunk 都会被使用,
- // 否则 `options.filename` 会用于作为 chunk 名。
- filename: string,
- /*文件的名字模板,可以使用和output相同的占位符,如[hash:7],7代表7位hash符号,默认是20位;
- * 默认名字与`output.filename` 或者 `output.chunkFilename`相同*/
- minChunks: number|Infinity|function(module, count) => boolean,
- // 在传入 公共chunk(commons chunk) 之前所需要包含的最少数量的 chunks 。
- // 数量必须大于等于2,或者少于等于 chunks的数量
- // 传入 `Infinity` 会马上生成 公共chunk,但里面没有模块。
- // 你可以传入一个 `function` ,以添加定制的逻辑(默认是 chunk 的数量)
- /*module.context代表chunk所以在的文件夹路劲,
- *module.resource代表该chunk的文件路劲
- *count chunk被引入的次数*/
- chunks: string[],
- // 通过 chunk name 去选择 chunks 的来源。chunk 必须是 公共chunk 的子模块。
- // 如果被忽略,所有的,所有的 入口chunk (entry chunk) 都会被选择。
- /*chunks和children是相同的作用,不同的是chunks只选择特定的子模块抽取公共模块,
- *而children是选择所有的子模块*/
- children: boolean,
- // 如果设置为 `true`,所有公共 chunk 的子模块都会被选择
- /*将子模块的公共模块打包进父 chunk */
- deepChildren: boolean,
- // 如果设置为 `true`,所有公共 chunk 的后代(子孙)模块都会被选择
- async: boolean|string,
- // 如果设置为 `true`,一个异步的 公共chunk 会作为 `options.name` 的子模块,和 `options.chunks` 的兄弟模块被创建。
- // 它会与 `options.chunks` 并行被加载。
- minSize: number,
- // 在 公共chunk 被创建立之前,所有 公共模块 (common module) 的最少大小。
- }
配置项介绍
不按照上面的顺序介绍,有些配置项很相似,容易弄混,按照我自己理解来解释。
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作为公共模块。
- //adminA
- require("./common")
- console.log("adminA")
- //adminA
- require("./common")
- console.log("adminB")
- entry: {
- adminA: "./adminA",
- adminB: "./adminB",
- },
- output: {
- path: path.join(__dirname, "dist"),
- filename: "[name].js"
- },
- plugins: [
- new webpack.optimize.CommonsChunkPlugin({
- name: "commons",
- }),
- ]
打包生成名为 commons的公共模块
同时,如果这个name和入口文件的name相同,那么入口文件直接被选择为打包来源,即直接指定name所指定的入口文件为公共模块;这个在很明确公共模块是什么的时候很有用,比如第三方库,可以直接指定。
names则是通过遍历names数组,执行多次该插件,免去写多个相同的代码(如果有这个需求)。例:
example2: 增加adminC,但是没有引入common.js,只有adminA和adminB引入了。
- //adminC
- console.log("adminC");
- entry: {
- adminA: "./adminA",
- adminB: "./adminB",
- adminC: "./adminC",
- },
- output: {
- path: path.join(__dirname, "dist"),
- filename: "[name].js"
- },
- plugins: [
- new BundleAnalyzerPlugin(),
- new webpack.optimize.CommonsChunkPlugin({
- name: "commons",
- }),
- ]
虽然也生成了commons.js但是其实里面没有任何东西(文件很小),adminA和adminB文件还是很大,也就是没有抽取公共模块:
可以用插件webpack-bundle-analyzer分析:common.js还是存在adminA.js和adminB.js里面
这个时候在入口文件直接指定公共模块commons:
example3
- entry: {
- adminA: "./adminA",
- adminB: "./adminB",
- adminC: "./adminC",
- //name和配置项的name相同
- commons: './common.js'
- },
可以从文件大小看出来,公共模块已经抽取出来了。
3. minChunks
被其他模块引用的次数 (默认是3),只有满足这个引入次数条件才会被抽取,如果设置成 Infinity (无限大,不可能满足),那么会立即打包成一个独立模块,不会抽取公共模块,用于公共模块很明确的时候或者想直接打包某一chunk。
例如前面的example2,也可以不用在入口指定公共模块,主要是因为minChunk的默认值是3,而common.js只被adminA和adminB引入了,也就是只引入了两次,所以不会被打包,我们这里将example2的minChunks设置2,再打包:
example4:
- entry: {
- adminA: "./adminA",
- adminB: "./adminB",
- adminC: "./adminC",
- },
- output: {
- path: path.join(__dirname, "dist"),
- filename: "[name].js"
- },
- plugins: [
- new BundleAnalyzerPlugin(),
- new webpack.optimize.CommonsChunkPlugin({
- name: "commons",
- minChunks: 2
- }),
- ]
从文件大小上可以看出,common.js已经抽取出来了:
minChunks也可以是一个函数,webpack会遍历所有来源chunk,逐一执行这个函数,函数返回true这个chunk才被提取为公共模块。这个函数用于更加精确的提取公共模块,如vue构建工具生成的配置文件,可以提取所有在文件夹node_modules中的模块:
example5:
- //这里是提取所有的第三方插件,如我这里有vue,vue-router,echarts
- //但是echarts太庞大了,需要和vue,vuer-router分离
- new webpack.optimize.CommonsChunkPlugin({
- name: 'vendor',
- minChunks(module) {
- /*module.context代表chunk所以在的文件夹路劲,
- *module.resource代表该chunk的文件路劲
- *count chunk被引入的次数*/
- return (
- module.resource &&
- /\.js$/.test(module.resource) &&
- module.resource.indexOf(
- path.join(__dirname, '../node_modules')
- ) === 0
- )
- },
- chunks: ["app"]
- }),
- //分离vue,vue-router,echarts是按需引入的,不太方便按这种方式抽取。
- new webpack.optimize.CommonsChunkPlugin({
- name: 'vue',
- minChunks: function (module) {
- return (module.resource && /\.js$/.test(module.resource) && (/vue/).test(module.resource))
- },
- chunks: ['vendor']
- }),
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。
- entry: {
- adminA: "./adminA",
- adminB: "./adminB",
- adminC: "./adminC",
- },
- output: {
- path: path.join(__dirname, "dist"),
- filename: "[name].js"
- },
- plugins: [
- new BundleAnalyzerPlugin(),
- new webpack.optimize.CommonsChunkPlugin({
- name: "commons",
- minChunks: 2,
- chunks: ['adminA', 'adminB']
- }),
- ]
结果: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。
- //adminA.js
- import('./childA');
- import('./childB');
- console.log("adminA");
- //chuildA
- import './jquery';
- import './common';
- console.log('childA');
- //chuildB
- import './jquery';
- import './common';
- console.log('childB');
- //webpack.config.js
- entry: {
- adminA: "./adminA",
- },
- output: {
- path: path.join(__dirname, "dist"),
- filename: "[name].js",
- chunkFilename: '[name].chunk.js'
- },
- plugins: []
不优化的打包结果:生成了两个异步的chunk,0和1,就是childA和childB。childA和childB都引入了common.js和jquery.js,体积很大。
我们试着优化,看能不能把异步加载的模块的公共模块抽取出来:
eample8:
- //webpack.config.js
- entry: {
- adminA: "./adminA",
- },
- output: {
- path: path.join(__dirname, "dist"),
- filename: "[name].js",
- chunkFilename: '[name].chunk.js'
- },
- plugins: [
- new webpack.optimize.CommonsChunkPlugin({
- name: "commons",
- minChunks: 2
- }),
]
结果:common.js和jquery.js并没有抽取出来成为公共模块,只是抽取了webpack代码分离功能的代码,因为代码分离出来的chunk,并不在chunk来源选择范围内(忽略了chunks选项,那么默认是全部的chunk来源,但是排除代码分离的chunk)。
我们加上children:true,并且需要把name设置成入口chunk的name,此处是adminA:
eample9:
- //webpack.config.js
- entry: {
- adminA: "./adminA",
- },
- output: {
- path: path.join(__dirname, "dist"),
- filename: "[name].js",
- chunkFilename: '[name].chunk.js'
- },
- plugins: [
- new webpack.optimize.CommonsChunkPlugin({
- name: "adminA",
- minChunks: 2,
- children: true
- }),
]
结果: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匹配
- entry: {
- adminA: "./adminA",
- },
- output: {
- path: path.join(__dirname, "dist"),
- filename: "[name].js",
- chunkFilename: '[name].chunk.js'
- },
- plugins: [
- new BundleAnalyzerPlugin(),
- new webpack.optimize.CommonsChunkPlugin({
- //要和入口chunk的name匹配
- name: "adminA",
- minChunks: 2,
- children: true,
- async: "async-chunk"
- }),
- ]
名为async-chunk.chunk.js就是我们分离代码的公共模块。
7.minSize
抽取公共代码之前,应该满足的文件的大小。如果抽取出来的公共代码文件大小只有几kb,这样会增加请求次数,还不如不抽取。
8.deepChildren
这个目前还不知道有什么用,和children差不多,children选择的是直接子代,deepChildren选择的是所有后代,但是目前我并没有发现它有什么用。
原文链接:https://blog.csdn.net/zy444263/article/details/85252477
[转]webpack——CommonsChunkPlugin的更多相关文章
- webpack CommonsChunkPlugin详细教程
1.demo结构: 2.package.json配置: { "name": "webpack-simple-demo", "version" ...
- [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 ...
- [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 ...
- webpack CommonsChunkPlugin 提取公共代码
1.项目结构 2.部分代码 module.js console.log('module.js'); index文件夹下的index.js require('../module.js'); consol ...
- Webpack+React+ES6开发模式入门指南
React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了Reac ...
- Webpack+React+ES6入门指南[转]
React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了Reac ...
- webpack 多页应用架构系列实战
阅读目录 1.webpack配置了解 2.webpack CommonsChunkPlugin公共代码剥离 3.了解ProvidePlugin的用途 回到顶部 1.webpack配置了解 webpac ...
- React的React Native
React的React Native React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React ...
- 关于webpack.optimize.CommonsChunkPlugin的使用二
Note:当有多个入口节点的时候,只有所有入口节点都引入了同一个模块的时候,webpack.optimize.CommonsChunkPlugin才会将那个模块提取出来,如果其中一个入口节点没有引入该 ...
随机推荐
- 企业级BI是自研还是采购?
企业级BI是自研还是采购? 上一篇<企业级BI为什么这么难做?>,谈到了企业级BI项目所具有的特殊背景,以及在"破局"方面的一点思考,其中谈论的焦点主要是在IT开发项目 ...
- Redis学习推荐资料合集
目录 一.官方 二.书籍 三.推荐博客 一.官方 redis官网 redis中文网 redis中文命令网 redis模块 redis-github源码 redis报告 二.书籍 <Redis开发 ...
- <转>C/S架构分析
系统架构师-基础到企业应用架构-客户端/服务器 开篇 上篇,我们介绍了,单机软件的架构,其实不管什么软件系统,都是为了解决实际中的一些问题,软件上为了更好的解决实际的问题才会产生,那么对于单机软 件的 ...
- 学习型的“文山表海无限发展公司”——《Office妖精是怎样炼成的》续1
本篇无故事情节版:https://www.cnblogs.com/officeplayer/p/14841590.html <Office妖精是怎样炼成的>http://blog.sina ...
- 小迪安全 Web安全 基础入门 第六天 - 信息打点-Web架构篇&域名&语言&中间件&数据库&系统&源码获取
一 . Web架构 语言.常用的Web开发语言有PHP,Java,Python,JavaScript,.net等.具体可参考w3school的介绍. 中间件. (1)常见的Web服务器中间件:IIS. ...
- 小迪安全 Web安全 基础入门 - 第四天 - 30余种加密编码进制&Web&数据库&系统&代码&参数值
一.密码存储加密 1.MD5值是32或16位由数字"0-9"和字母"a-f"所组成的字符串 2.SHA1加密的密文特征与MD5类似,但位数是40位 3.NTLM ...
- 一篇文章讲明白vue3的script setup,拥抱组合式API!
引言 vue3除了Composition API是一个亮点之外,尤大大又给我们带来了一个全新的玩意 -- script setup,对于setup大家相信都不陌生,而对于script setup有些同 ...
- 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 ...
- js中的jQuery Validate增加手机号码验证
$.validator.addMethod("isPhone", function(value,element) { var length = value.length; var ...
- win10+vs2015编译nanogui
!!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!! 作者:mohist 说明: A.OS : win10 1909 ,没有配置OpenGL开发环境的 经历. B. ...