简述一波
最近前端面试被考webpack优化的应该不少,无疑webpack的优化是我们前端必须掌握的知识点之一,所以该文从打包速度分析
,打包优化
入手。webpack的基础用法就不举例了,直接走一波好吧。
一、打包分析
1.1 打包速度分析
这里用到了speed-measure-webpack-plugin
可以看每个plugin
跟loader
打包时间,用来对比优化前后差距的,安装就对了:
npm i speed-measure-webpack-plugin -D
配置的话cli2、跟cli3是有区别的
//webpack.config.js ------------->cli2
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap(webpackConfig, {
plugins: [
//所用到的插件
]
});
// cli3
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasurePlugin({
outputFormat: 'human'
})
module.exports = {
configureWebpack: smp.wrap({
plugins: []
})
}
配置完再跑项目就可以看到致死量:
1.2 打包体积
看完打包速度,还要看下模块的大小。安装插件webpack-bundle-analyzer
,安装完后可以在端口8888
配置的话直接简单,引入然后直接写进plugins
就ok了
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const webpackConfig:{
...
plugins: [
...
new BundleAnalyzerPlugin() //一定要放在其他插件的后面
]
}
二、打包优化
2.1 多线程打包
目前用的比较多的多线程打包有这三:
-
thread-loader (webpack4.0推荐使用这个)
-
parallel-webpack
-
HappyPack
我的项目比较老就用了:HappyPack. 就能让 Webpack 做到这点,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。安装
npm install --save-dev happypack
//webpack.config.js
const HappyPack = require('happypack')
const os = require('os')
//os.cpus返回一个对象数组,包含所安装的每个 CPU/内核的信息
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
const webpackConfig:{
...
plugins: [
...
new BundleAnalyzerPlugin() //一定要放在其他插件的后面
++++
new HappyPack({
id: 'happy-js',
loaders: ['babel-loader?cacheDirectory=true'],
threadPool: happyThreadPool,//共享进程池
})
]
...
module: {
rules:[
{
test: /\.js$/,
// loader: 'babel-loader', //用happypack替代
loader: 'happypack/loader?id=happy-js', // 增加新的HappyPack构建loader
include: [resolve('./'), resolve('test'), resolve('../../node_modules/webpack-dev-server/client')],
},
]
}
}
2.2 代码压缩
webpack版本比较老用uglifyjs-webpack-plugin
,比较新的用terser-webpack-plugin
。
我们这里用uglifyjs-webpack-plugin
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
plugins:[
new UglifyJsPlugin({
uglifyOptions: {
mangle: {
safari10: true
},
compress: {
warnings: false,
drop_debugger: false,//去除debug和console
drop_console: false,
parallel: true, //使用多进程并行运行来提高构建速度
}
},
sourceMap: config.build.productionSourceMap,
cache: true,
parallel: true
}),
]
2.3 开启缓存
2.3.1 hard-source-webpack-plugin
在webpack4.0开始就可以用hard-source-webpack-plugin
使用方法也很简单,安装
npm i -D hard-source-webpack-plugin
// webpack.config.js
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
// ......
plugins: [
new HardSourceWebpackPlugin() // <- 直接加入这行代码就行
]
}
2.3.2 dllPlugin
目前dll已经不维护了,主要原理就是把第三方依赖提前打包,把打包好的json映射文件引入项目,这样就可以不用每次都去打包这些没改变的第三方依赖
使用方法比hardSourceWebpackPlugin繁琐:
//新建webpack.dll.conf.js
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: {
vendor: ['vue', 'vuex','vue-router',...所需依赖]
},
output: {
path: path.resolve(__dirname, '../static/js'),
filename: 'dll.[name].js'
},
plugins: [
new webpack.DllPlugin({
path: '[name]-manifest.json',
name: '[name]',
context: __dirname
})
]
}
执行webpack --config ./build/webpack.dll.conf.js会在static/js文件夹下生成dll.vendor.js以及在根目录下生成mainfest.json,接着在webpack.config.js中引入
// webpack.base.conf.js
const manifest = require('../manifest.json')
// 插件中引入
plugins: [
new webpack.DllReferencePlugin({
mainfest
})
]
最后再index.html中映入就可以了
<script type="text/javascript" src="/static/js/dll.vendor.js"></script>