webpack4优化
背景分析
笔者现在的项目是一个通过webpack4构建的多入口工程,随着项目入口的增多,业务代码不断增加,项目深度不断延伸,团队里有个小妹子就开始抱怨了,构建时长时间太长了......于是乎,就要想着如何优化了。
这边以当前团队中用到的一个项目为例,在不断扩展业务模块的同时,首次构建时间已经达到了70s+,这就造成了组员每人执行dev或者build都可以去泡一杯茶再回来看看构建好了没,体验很差。
优化步骤
- 抽离文件 => dllPlugin
- 多线程编译 => happypack
- 缓存文件 => cache-loader
dllPlugin抽离文件
webpack.dll.config.js配置,抽离公共库,这里用到了webpack.DllPlugin这个插件,这个过程会生成manifest.json 的文件
dll: {
vue: ['vue', 'vue-router', 'vuex'],
axios: ['axios'],
clipboard: ['clipboard'],
vueAwesomeSwiper: ['vue-awesome-swiper'],
qs: ['qs'],
nativeshare: ['nativeshare'],
mintUi: ['mint-ui'],
jquery: ['jquery']
}
const path = require('path');
const webpack = require('webpack');
const config = require('../config');
module.exports = {
entry: config.dll,
output: {
path: path.join(config.build.assetsRoot, config.build.assetsDllRoot),
filename: '[name]_[hash].dll.js',
library: '[name]_[hash]_library'
},
plugins: [
new webpack.DllPlugin({
path: path.join(config.build.assetsRoot, config.build.assetsManifestRoot, '[name]-manifest.json'),
name: '[name]_[hash]_library'
})
]
};
webpack.DllReferencePlugin,通过引用 dll 的 manifest 文件来把依赖的名称映射到模块的 id 上
const dllPlugin = () => {
const { dll } = config;
return Object.keys(dll).map(item => new webpack.DllReferencePlugin({
manifest: require(path.join(config.build.assetsRoot, config.build.assetsManifestRoot, `${item}-manifest.json`))
}));
};
plugins: [
...dllPlugin()
]
到此为止,通过上述步骤把公共库提前分离,我们在运行下dev或者build看下编译时间
happypack多线程编译
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
rules: [{
test: /\.js$/,
use: ['happypack/loader?id=js'],
exclude: /node_modules/
}]
plugins: [
new HappyPack({
id: 'js',
threadPool: happyThreadPool,
loaders: [ 'babel-loader' ]
})
]
用上happypack,经过2次优化加速后,查看运行速度,缩减到52s,比第一次减少了20s
- happypack的运行机制
缓存cache-loader
第二次构建时,利用上一次编译的缓存,而不是再次重复编译
module.exports = {
module: {
rules: [
{
test: /\.ext$/,
use: [
'cache-loader',
...loaders
],
include: path.resolve('src')
}
]
}
}
第三次优化后查看编译效率,从70s+到17s+,当然这不是极致,优化还在进行
总结一下
通过本次优化,其核心优化的方向即一下三点
- 提取分离那些不怎么变动的公共库 dllPlugin
- 多核多线程打包happypack,多核,更是充分利用了硬件优势
- 缓存cache-loader,缓存是为了让二次构建时,不需要再去做重复的工作
推荐几个webpack小工具
- speed-measure-webpack-plugin 查看每一个 Loader 和 Plugin 的时效
- webpack-bundle-analyzer 打包文件分析工具