随着前端项目变得越来越庞大,代码的组织和管理越来越困难,Webpack 工具在前端开发中扮演着越来越重要的角色。其中,Webpack CommonChunkPlugin 是一个优秀的插件,它能够帮助我们大大优化编译后的资源文件,减少对服务器的请求,加速页面的加载速度。本文将对该插件进行详细的讲解,包括使用方法、实现原理、应用场景等内容。
CommonChunkPlugin 的使用方法
Webpack CommonChunkPlugin 插件是在 Webpack 3.x 版本中引入的,用于提取公共代码。我们可以在 Webpack 的配置文件中通过以下代码来使用该插件:
plugins: [ new webpack.optimize.CommonsChunkPlugin(options) ]
其中,options 是一个对象,包含了各种配置参数。
name
:提取出来的公共代码块的名称,可以使用占位符([name]、[id]、[hash])进行自定义。filename
:提取出来的公共代码块的文件名,也可以使用占位符进行自定义。chunks
:表示需要提取公共代码的 chunk 的范围。如果是字符串数组,则表示需要提取的入口 chunk。minChunks
:最小的 chunk 数量,如果某个 JavaScript 模块被多少 chunk 引用,才会被提取出来。children
:表示是否在子级 chunk 中寻找公共代码。deepChildren
:将选择范围的子级 chucks 的依赖子树中的公共模块提取到公共块中。
这里给出一个常见的配置参数示例:
plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.[hash].js', minChunks: function (module) { // 如果模块在 node_modules 目录下,则认为是第三方模块 return module.context && module.context.indexOf('node_modules') !== -1; } }), new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', filename: 'manifest.[hash].js' }) ]
该配置文件的意思是,先提取出第三方模块,并打包到 vendor.[hash].js 文件中;然后再提取出 webpack 的运行时代码,并打包到 manifest.[hash].js 文件中。这样可以避免因为版本更新而导致 vendor 文件的重新下载,并且可以通过缓存技术加快页面的加载速度。
CommonChunkPlugin 的实现原理
Webpack CommonChunkPlugin 插件的实现原理是利用 Webpack 对多个 JavaScript 入口文件的打包方式。Webpack 会将多个入口文件在递归地解析依赖关系后统一打包成一个 bundle。在打包过程中,Webpack 会先根据配置的 chunks 分类,然后提取出公共代码,生成一个新的文件。原来每个 HTML 页面用到的公共代码就不再需要重复下载了。
如下面这张图所示,我们有两个 JavaScript 文件 A.js 和 B.js,它们都引用了一个公共模块 C.js。使用 CommonChunkPlugin 插件后,Webpack 在打包时会先将 entry 中的 js 文件打包成 bundle,然后将公共模块提取出来,生成新的公共模块文件 common.js,供其他 js 文件复用。
CommonChunkPlugin 的应用场景
常见的应用场景有以下几种:
- 提取第三方库。将第三方库单独打包成一个文件,避免反复下载和编译;
- 提取公共模块。当多个页面之间共用一些代码时,可以将这些公共代码提取出来,放到一个独立的文件中,对于多个入口文件中存在的相同依赖可以减少打包后文件的大小;
- 避免 vendor 中 webpack runtime 代码重复。Webpack 在运行时,有一部分代码不能通过 hash 值缓存起来,也就是说每次打包时都会重新生成,这样就导致了每次改变应用代码后,vendor 和 manifest 的 hash 值也会变化。这使得每次都需要重新下载这两个文件。为了解决这个问题,我们可以将 vendor 和 manifest 提取到一个单独的文件中,这样即使应用代码发生变化,也不会影响到 vendor 和 manifest 的 hash 值,从而实现持久化缓存。
示例代码
我们可以通过以下示例代码来更加深入地理解和掌握 CommonChunkPlugin 插件的使用方法和效果。
- 需要准备的文件
以下是我们假设在一个项目中你一共有三个页面,分别是 home.html, page1.html 和 page2.html。这三个页面用到的 JavaScript 代码分别如下:
home.js
console.log('home.js'); import '../../css/home.css'; import '../../js/common.js';
page1.js
console.log('page1.js'); import '../../css/page1.css'; import '../../js/common.js';
page2.js
console.log('page2.js'); import '../../css/page2.css'; import '../../js/common.js';
- 未使用 CommonChunkPlugin 插件时的打包情况
我们可以看到,home.js, page1.js, page2.js 都把公共脚本 common.js 引入。我们使用 Webpack 进行打包,在 home.html, page1.html 和 page2.html 中都引入各自需要的 JavaScript 文件,是不是有些浪费呢?
在该配置下打包后的文件大小和数量如下:
可以看到,我们生成了三个 HTML 文件和三个 JavaScript 文件,此时,如果在浏览器中打开这三个页面,会发现每个页面都会下载各自需要的 JavaScript 文件,其中包括 common.js,这是一种明显的资源冗余。
- 使用 CommonChunkPlugin 插件时的打包情况
我们可以通过以下方法解决这个问题:
- 在 webpack 的配置文件中添加以下代码:
// 此配置是为了区分 webpack 和业务代码 var webpackConfig = { entry: { home: './src/pages/home/home.js', page1: './src/pages/page1/page1.js', page2: './src/pages/page2/page2.js', vendor: ['jquery'] }, output: { path: path.join(__dirname, 'dist'), filename: 'js/[name].[hash:8].js' }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'common', filename: 'js/common.[hash:8].js', minChunks: 2 }), new htmlWebpackPlugin({ filename: 'views/home.html', template: './src/pages/home/home.html', inject: true, hash: true, chunks: ['common', 'home'] }), new htmlWebpackPlugin({ filename: 'views/page1.html', template: './src/pages/page1/page1.html', inject: true, hash: true, chunks: ['common', 'page1'] }), new htmlWebpackPlugin({ filename: 'views/page2.html', template: './src/pages/page2/page2.html', inject: true, hash: true, chunks: ['common', 'page2'] }) ] }; module.exports = webpackConfig;
这部分代码中,我们首先定义了三个页面的入口,然后在 output 属性中配置了打包输出的路径和文件名。我们还将 jquery 全局引入,使其成为一个公用模块。在 plugins 属性中,添加了 CommonChunkPlugin 插件,将公共模块打包到名为“common”的文件中。接着使用 html-webpack-plugin 插件将打包后的 js 和 css 文件引入 html 中。
- 更新 common.js 的引入方式
在 home.js, page1.js 和 page2.js 中,都需要引入 common.js。我们修改 require('../../js/common.js')
为 require('common')
,从而可以引用打包后的公共模块。
修改后的 home.js, page1.js 和 page2.js 如下:
home.js
console.log('home.js'); import '../../css/home.css'; require('common');
page1.js
console.log('page1.js'); import '../../css/page1.css'; require('common');
page2.js
console.log('page2.js'); import '../../css/page2.css'; require('common');
最后,我们在终端中输入命令 npm run build
。打包后,会生成以下文件:
可以看到,webpack 打包了四个文件。其中 vendor, common 分别为第三方库和公共脚本,被单独打包到一个独立的文件中。在我们的三个页面中注入的 js 文件都是 chunk 文件,这些 chunk 文件只包含各自页面所需的代码,不包含公共代码,这样就解决了前面提到的资源冗余问题,也提高了页面的加载速度。
总结
Webpack CommonChunkPlugin 插件是 Webpack 提供的一个优秀工具,能够提高前端项目的代码管理和资源文件打包效率。通过本文的介绍,可以更深入了解该插件的使用方法和实现原理,并运用到实际的项目中。我们可以通过打包多个入口文件,将公共代码分离出来,让页面只会下载各自的需要的代码,避免了资源浪费和冗余的情况,提高页面的加载速度,从而更好地满足用户的需求。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a095acadd4f0e0ff8da202