avatar

目录
webpack 性能优化(2)DllPlugin&DllReferencePlugin

场景需求

在打包一个 react 的项目的时候,会把 react 和 react-dom 这两个库打包进来。这两个库很大且基本不会变,所以如果每次打包都要打包这两个第三方包的话,浪费时间,消耗性能

所以可以将 react 和 react-dom 单独打包好,然后动态链接引入即可。第二次打包时,发现react和react-dom已经被打包好了,那么就不需要再打包了,这样就大大提升了性能

引入

在 src 下新建 test.js

Javascript
module.exports = 'wangyi'

创建 webpack.config.react.js 用来打包 test.js

Javascript
//  webpack.config.react.js 
let path = require('path');

module.exports = {
mode:'development',
entry:{
test:'./src/test.js'
},
output:{
filename:'[name].js',
path:path.resolve(__dirname,'dist')
}
}

使用上面的配置文件执行 webpack

powershell
npx webpack --config webpack.config.react.js

打包得到 /dist/test.js 里面是一个立即执行函数表达式,返回 module.exports 的 ‘wangyi’

为了使用一个变量去接收导出的值,可以修改配置文件的 output 属性

Javascript
//  webpack.config.react.js 
let path = require('path');

module.exports = {
mode:'development',
entry:{
test:'./src/test.js'
},
output:{
filename:'[name].js',
path:path.resolve(__dirname,'dist'),
library:'a',//这样打包后的结果就被变量a接收
libraryTarget:'var',//commonjs、umd、var、this等等,默认var,这样就相当于var a = 打包后的结果
}
}

实际使用(react 为例)

第三方包 react ,react-dom 也可以像 test.js 提前打包好,用一个变量去接收,使用的时候直接引入已经打包好的动态链接库

打包使用的配置文件 webpack.config.react.js

Javascript
//  webpack.config.react.js 
let path = require('path');
let webpack = require('webpack')

module.exports = {
mode: 'development',
entry: {
react: ['react', 'react-dom']
},
output: {
filename: '_dll_[name].js', // 生成 _dll_react.js
path: path.resolve(__dirname, 'dist'),
library: '_dll_[name]',
// libraryTarget: 'var'
},
plugins: [
new webpack.DllPlugin({
name: '_dll_[name]',//这个name要与output中的library同名
path: path.resolve(__dirname, 'dist', 'manifest.json')
})
]
}

打包时使用 webpack 内置插件 DllPlugin 根据之前打包的结果生成动态链接库的清单 manifest.json,每次打包时会先去查找下清单里是否已经存在这个依赖,如果已经存在,则不打包,如果还没存在,则需要打包

运行npx webpack --config webpack.config.react.js ,得到打包j结果 _dll_react.js 动态链接库文件和 manifest.json 清单

为了使用动态链接库,在 src 下的 index.html 引入 _dll_react.js ,路径/表示根目录,打包后的’dist/index.html’ 正好可以引用,也可使用当前路径 ./

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src="/_dll_react.js"></script> <!-- 表示根目录 -->
</body>
</html>

现在引入 react,react-dom 等第三方库的时候,首先查找是否在 manifest 清单中,不在清单中会打包,在清单中不打包,直接使用 html 引入的动态链接库;判断是否在清单中需要在打包时使用 DllReferencePlugin

Javascript
// webpack.config.js
let webpack = require('webpack')
module.exports = {
plugins:[
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dist', 'manifest.json')
})
]
}

这样再打包时,react,react-dom不再打包了,直接使用第一次打包生成的动态链接库,文件小很多

文章作者: GRIT
文章链接: https://grit0821.github.io/Blog/2020/02/04/webpack-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%EF%BC%882%EF%BC%89DllPlugin-DllReferencePlugin/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Grit's World