使用 webpack 提取公共代码(多页应用)


作者:Seiya

时间:2019年07月09日


为什么要提取公共代码


我们都知道,目前前端开发中,主流的开发模式为模块化开发。为了减少代码冗余,提高加载速度,我们需要提取出公共代码。这里就用到了 optimization.splitChunks 配置。

注意:

4.0 版本用 optimization.splitChunks 配置替换了 3.0 版本的 CommonsChunkPlugin 插件。



基础库分离


思路

将第三方通过 CDN 进行引入,而不是打入 bundle 中。比如:将 react、react-dom 基础包通过 CDN 进行引入,而不是直接打包进去。


方法

使用 html-webpack-externals-plugin 插件,具体配置如下:

const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');

module.exports = {
	...
	plugins: [
		new HtmlWebpackExternalsPlugin({
			externals: [
				{
					module: 'react',
					entry: 'https://11.url.cn/now/lib/16.2.0/react.min.js',
					global: 'React',
				},
				{
					module: 'react-dom',
					entry: 'https://11.url.cn/now/lib/16.2.0/react-dom.min.js',
					global: 'ReactDOM',
				},
			]
		}),
	]
}

编写完配置后,我们还需要在 html 中引入脚本,如下所示:

<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react.min.js"></script>
<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react-dom.min.js"></script>


利用 SplitChunksPlugin 进行公共脚本分离


准备

创建 pageA.js 和 pageB.js 分别作为两个入口文件。同时,这两个入口文件同时引用 subPageA.js 和 subPageB.js,而 subPageA.js 和 subPageB.js 又同时引用 module.js 文件。


  • module.js

    export default "module";
    

  • subPageA.js

    import "./module";
    export default "subPageA";
    

  • subPageB.js

    import "./module";
    export default "subPageB";
    

最后,我们封装入口文件。为了让情况更真实,这两个入口文件又同时引用了 lodash 这个第三方库:

  • pageA.js

    import "./subPageA";
    import "./subPageB";
    
    import * as _ from "lodash";
    console.log("At page 'A' :", _);
    
    export default "pageA";
    

  • pageB.js

    import "./subPageA";
    import "./subPageB";
    
    import * as _ from "lodash";
    console.log("At page 'B' :", _);
    
    export default "pageB";
    


编写 webpack 配置


const path = require('path');

module.exports = {
	mode: 'development',
	entry: {
		pageA: './src/pageA.js',
		pageB: './src/pageB.js'
	},
	output: {
		filename: '[name].bundle.js',
		path: path.resolve(__dirname, 'dist'),		// 打包文件的输出目录
		chunkFilename: '[name].chunk.js'
	},
	optimization: {
		splitChunks: {
			cacheGroups: {
				/* 抽离自己写的公共代码,名字可以随意起 */
				common: {
					name: 'common',
					/**
					 * chunks 参数说明:
					 * 		- async:		异步引入的库进行分离(默认)
					 * 		- initial: 同步引入的库进行分离
					 * 		- all:			所有引入的库进行分离(推荐)
					 */
					chunk: 'all',
					minChunks: 2										 // 设置最小引用次数
					minSize: 30000,									 // 分离包体积的大小
					priority: 0
				},
				/* 抽离第三方插件 */
				vendor: {
					name: 'vendor',									// 打包后的文件名,任意命名
					test: /[\\/]node_module[\\/]/,	// 匹配出需要分离的包(在node_modules范围内进行匹配)
					chunk: 'all',

					/* 针对第三方库,通过设置 priority 来让其先被打包提取,最后再提取剩余代码 */
					priority: 10										// 设置优先级,防止和自定义的公共代码提取时被覆盖,不进行打包
				}
			}
		}
	}
}

更多配置属性,请参考官方文档 optimization.splitChunks

最后更新时间: 2019-7-16 12:54:06