webpack优化思路(学习笔记)
高频面试题:
webpack
了解多少,如何通过webpack
做优化?
一、速度指标
1.webpack的stats
颗粒度比较粗的分析构建速度
"build:stats": "webpack --profile --json=compilation-stats.json"
2.webpack的speed-measure-webpack-plugin
- 分析整个打包总耗时
- 每个插件和loader的耗时情况
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const webpackConfig = smp.wrap({
plugins: [new MyPlugin(), new MyOtherPlugin()],
});
3.webpack的webpack-bundle-analyzer
- 依赖的第三方模块文件大小
- 业务里面的组件代码大小
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
二、构建速度
1.多进程/多实例解析资源:thread-loader
- 作用:提升构建速度
- 原理:webpack每次解析一个模块时,thread-loader会将它的依赖分配给worker线程中
{
test: /.js$/,
use: [
{
loader: 'thread-loader',
options: {
workers: 2
}
},
'babel-loader'
]
},
2.多进程/多实例压缩:terser-webpack-plugin
- 作用:提升构建速度
const TerserPlugin = require("terser-webpack-plugin");
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
})
],
},
三、打包体积
1.SplitChunksPlugin
可以用来分离公共的资源或者公共的方法,减少代码体积,例如:
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /(react|react-dom)/,
name: 'vendors',
chunks: 'all',
}
},
}
},
};
2.three-shaking
作用:擦除以下代码
- 代码不会被执行,不可到达
- 代码执行的结果不会被用到
- 代码只会影响死变量(只写不读)
原理:利用ES6模块的特点,对代码在ast阶段进行今天分析
- 只能作为模块顶层的语句出现
- import的模块名只能是字符串常量
- import binding是immutable的 触发:只需要打开mode:'production'
3.Scope Hoisting
作用:webpack打包后的代码会以闭包的形式存在,通过scope hoisting可以减少函数声明开销和内存开销
原理:将所有模块的代码按照引用顺序放在一个函数作用域里,然后适当的重命名一些变量以防止变量名冲突 触发:
- 自动:只需要打开mode:'production'
- 手动: 在plugins中增加以下代码
new webpack.optimize.ModuleConcatenationPlugin();
4.代码分割和动态import
webpack可以将代码分割成chunks,当代码运行到需要它们的时候再进行加载,适用场景是:
- 抽离相同的代码到一个共享块
- 脚本懒加载,使得初始下载的代码更小 启动:
- 如果再.babelrc中的preset中有@babel/preset-env,那么就已经默认支持了dynamic import
{
"presets": [
"@babel/preset-env"
],
"plugins": []
}
- 如果仅仅只是转译import,那么,只需要在.babelrc的plugins中加入 @babel/plugin-syntax-dynamic-import
{
"presets": [],
"plugins": [
"@babel/plugin-syntax-dynamic-import"
]
}
这个包即可
5.CSS的擦除:purgecss-webpack-plugin
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const PATHS = {
src: path.join(__dirname, 'src')
}
// ...
plugins: [
new PurgeCSSPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
}),
]
6.图片压缩:image-webpack-loader
rules: [{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
},
],
}]
7.动态babel-pollyfill
每一个设备终端可能对于babel-pollyfill的需求不一样,甚至不需要,那么,动态babel-pollyfill需要通过User Agent的判断,进行按需加载。 比如:
<script scr="http://cdn.polyfill.io/v2/polyfill.min.js"></script>
总结:当前构建体积方案的方式有
- 1.SplitChunksPlugin
- 2.three-shaking
- 3.Scope Hoisting
- 4.动态import按需加载
- 5.CSS的擦除:purgecss-webpack-plugin
- 6.图片压缩:image-webpack-loader
- 7.动态babel-pollyfill
转载自:https://juejin.cn/post/7184945727410274341