介绍:
把复用性较高的第三方模块打包到动态链接库中,在不升级这些库的情况下,动态库不需要重新打包,每次构建只重新打包业务代码。
背景:
在负责的一个react服务端渲染项目中,由于react和react-dom等第三方的包很大,而且一般都不会改变,所以打包时不会将它打包进去。
描述:
之前使用的方式是webpack的externals配置项+script标签外链
//webpack.config.js externals: { react: { amd: 'react', root: 'React', commonjs: 'react', commonjs2: 'react' }, 'react-dom': { amd: 'react-dom', root: 'ReactDOM', commonjs: 'react-dom', commonjs2: 'react-dom' } },
在html中引入react和react-dom
<script src="//j1.58cdn.com.cn/escstatic/common/react/16.6.0/react.production.min.js"></script> <script src="//j1.58cdn.com.cn/escstatic/common/react/16.6.0/react-dom.production.min.js"></script>
这样容易造成的问题是我们react项目服务端和客户端的react版本可能无法保持一致。
dllplugin + DllReferencePlugin
什么是DLL
DLL(Dynamic Link Library)文件为动态链接库文件,在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。
可以使用这两者帮助我们进行代码的切割以及连接到打包的js中。
DllPlugin:打包第三方依赖库文件
DllReferencePlugin:连接到我们打包出的dll文件
使用步骤:
1.对需要打包的第三方插件写一个配置文件(也可以不写,我主要是为了不写两遍配置)
module.exports = { library : { react: ['react', 'react-dom'] } }
2.在项目根目录新建一个文件 webpack.dll.config.js
//webpack.dll.config.js const path = require("path"); const webpack = require("webpack"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); const { library } = require('./dll.config'); const dllPath = path.join(process.cwd() + '/public/vendors') // dll文件存放的目录 module.exports = { // 入口文件 entry: { ...library }, // 输出文件 output: { publicPath: '/', path: dllPath, filename: "MyDll.[name].js", library: "[name]_[hash]" }, plugins: [ // 清除之前的dll文件 new CleanWebpackPlugin(), new webpack.DllPlugin({ path: path.join(dllPath, "[name]-manifest.json"), name: "[name]_[hash]" }) ] };
3.执行命令打包出dll文件 npm run dll
"dll": "webpack --config ./webpack.dll.config.js -p"
打包出的文件如下
4.在html中引入我们打包出的dll.js文件
<script src="/vendors/Mydll.react.js"></script>
如果使用了html-webpack-plugin,那就不用手动的引入。使用插件 HTMLIncludeAssetsPlugin
new HTMLIncludeAssetsPlugin({ assets: 'MyDll.react.js', append: false, publicPath: '/vendors' }),
5.使用动态链接库DllReferencePlugin,在webpack打包的时候如果有我们dllplugin里配置文件,那就不打包,而是通过动态链接库去查找对应的文件。(产出的manifest
文件就用在这里,给主构建流程作为查找dll的依据:DllReferencePlugin去 manifest.json 文件读取 name 字段的值,把值的内容作为在从全局变量中获取动态链接库中内容时的全局变量名,因此:在 webpack.dll.config.js 文件中,DllPlugin 中的 name 参数必须和 output.library 中保持一致。)
//webpack.config.js new webpack.DllReferencePlugin({ manifest: './public/vendors/react-manifest.json' })
AutoDllPlugin
有DLLPlugin插件,我们现在为什么还需要一个AutoDllPlugin插件呢?该插件的具体的作用是什么呢?
从上面的dllplugin的使用可以看出配置很多,并且使用步骤也比较复杂。所以AutoDllPlugin就是为了帮我们简化操作。
推荐 AutoDllPlugin HtmlWebpackPlugin,这两个插件一起使用,因为它可以节省手动将DLL包添加到自己的HTML中
1.首先需要安装命令如下:
如果是webpack4以下的版本:如下命令安装:
npm install --save-dev autodll-webpack-plugin@0.3
如果是webpack4版本的话,如下命令安装:
npm install --save-dev autodll-webpack-plugin
2.在webpack.config.js 使用方式如下:
//webpack.config.js const htmlWebpackPlugin = require('html-webpack-plugin'); const AutoDllPlugin = require('autodll-webpack-plugin'); //... plugins: [ new htmlWebpackPlugin({ filename: 'index.html', template: './src/template.html', inject: true, minify: { removeComments: true, // collapseWhitespace: true, // removeAttributeQuotes: true } }), new AutoDllPlugin({ inject: true, filename: '[name]_[hash].js', entry: { vendors: ['react','react-dom'] } }) ],
更多的配置项,请看官网
参考文献:
https://cloud.tencent.com/developer/article/1470725