webpack打包时会将第三方包和业务代码一起打包,实际上第三方包不经常变化,不需要每次都参与打包。
如果把第三方包打包成一个库,供项目使用,那么打包第三方包的操作只需要在依赖包发生变化时进行一次即可。并且将第三方包提取出来,业务代码的打包速度也会提高。
打包DLL
例如一般react项目都会用到react和react-dom两个包,可以把它们提取成一个库,提供react项目使用,这样打包该项目的时候react和react-dom就不会参与打包了。
webpack 提供了一个插件:DllPlugin,可以把多个包打包成一个库。
// webpack.dll.js 打包dll的配置文件const path = require('path')const webpack = require('webpack')const TerserPlugin = require('terser-webpack-plugin')module.exports = {mode: "production",entry: {react: ['react', 'react-dom'], // 将react和react-dom打包成一个库,这里有多少个数组就会生成多少个库文件jquery: ['jquery']},output: {path: path.resolve(__dirname, 'dll'),filename: 'dll_[name].js',library: 'dll_[name]'},optimization: {minimizer: [new TerserPlugin({extractComments: false // 不生成库的LICENCE文件}),],},plugins: [new webpack.DllPlugin({name: 'dll_[name]',path: path.resolve(__dirname, './dll/[name].manifest.json')})]}
生成的库:
manifest.json 用来指示库的位置索引。
比如react的库的内容如下:
使用DLL
webpack提供的另外一个插件:DllReferencePlugin 可以加载已经打包的库。
plugins: [new HtmlWebpackPlugin({title: 'copyWebpackPlugin',template: './public/index.html'}),new webpack.DllReferencePlugin({context: resolveApp('./'), // 指定上下文,和manifest.json对应的库文件的位置,如果在同一个文件夹,写 ./manifest: resolveApp('./dll/react.manifest.json') // 指定manifest.json的路径}),]
这样webpack打包就不会将react一并打包,但是这样打包生成的index.html文件并不会引用库文件,需要另外的插件:AddAssetHtmlPlugin 将库文件添加到index.html的script标签。
plugins: [new HtmlWebpackPlugin({title: 'copyWebpackPlugin',template: './public/index.html'}),new webpack.DllReferencePlugin({context: resolveApp('./'), // 指定上下文,和manifest.json对应的库文件的位置,如果在同一个文件夹,写 ./manifest: resolveApp('./dll/react.manifest.json') // 指定manifest.json的路径}),new AddAssetHtmlPlugin({outputPath: 'js', // 输出到 js 文件夹filepath: resolveApp('./dll/dll_react.js') // 库文件路径})]

发现生成的index.html,引用的库文件总是放在一个auto文件夹,但这个文件夹事实上并不存在,在这个例子中dll_react.js放在了js文件夹中,可能是 bug。所以把AddAssetHtmlPlugin配置的输出文件夹也改成auto会比较好,否则要去手动更改index.html。
