webpack不仅可以优化构建速度,也可优化项目性能,是项目优化的重要一环。
构建速度优化
常见方法有:
- 优化loader配置
- 合理使用resolve.extensions
- 优化resolve.modules
- 优化resolve.alias
- 使用DLLPlugin插件
- 使用cache-laoder
- terser启用多线程
- 合理使用sourceMap
优化loader配置
在使用loader时通过配置include、exclude等
如babel-loadermodule.exports = {module: {rules: [{// 如果项目源码中只有 js 文件就不要写成 /\.jsx?$/,提升正则表达式性能test: /\.js$/,// babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启use: ['babel-loader?cacheDirectory'],// 只对项目根目录下的 src 目录中的文件采用 babel-loaderinclude: path.resolve(__dirname, 'src'),},]},};
合理使用resolve.extensions
在解析无扩展名文件时指定文件扩展名
:::warning 不可随意将所有扩展名写入 :::module.exports = {...extensions:[".warm",".mjs",".js",".json"]}
优化resolve.modules
指定第三方依赖所在路径module.exports = {resolve: {// 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤// 其中 __dirname 表示当前工作目录,也就是项目根目录modules: [path.resolve(__dirname, 'node_modules')]},};
优化resolve.alias
为常用路径添加别名module.exports = {...resolve:{alias:{"@":path.resolve(__dirname,'./src')}}}
使用DLLPlugin插件
DLL全称动态链接库,旨在实现共享函数库。将不常改变的带边抽成一个共享的库。打包DLL库
使用webpack内置的DllPluginmodule.exports = {...plugins:[new webpack.DllPlugin({name:'dll_[name]',path:path.resolve(__dirname,"./dll/[name].mainfest.json")})]}
引入DLL库
使用内置的DLLReferencePlugin对mainfest.json解析,找到需要的DLL库并通过AddAssetHtmlPlugin添加到html中module.exports = {...new webpack.DllReferencePlugin({context:path.resolve(__dirname,"./dll/dll_react.js"),mainfest:path.resolve(__dirname,"./dll/react.mainfest.json")}),new AddAssetHtmlPlugin({outputPath:"./auto",filepath:path.resolve(__dirname,"./dll/dll_react.js")})}
使用cache-laoder
在一些性能开销较大的loader之前使用cache-loader,提升二次构建速度。module.exports = {module: {rules: [{test: /\.ext$/,use: ['cache-loader', ...loaders],include: path.resolve('src'),},],},};
terser启用多线程
module.exports = {optimization: {minimizer: [new TerserPlugin({parallel: true,}),],},};
合理使用sourceMap
devtool配置获取的信息越详细使构建速度越慢,所以需合理配置devtool
项目性能优化
- js、css、html代码压缩
- 图片压缩
- 文件大小压缩
- TreeShaking
- 代码分离
- 内联chunk
js、css、html代码压缩
```javascript // js // 使用terser工具集,它可以丑化、压缩js代码 // production模式下默认使用 const TerserPlugin = require(‘terser-webpack-plugin’) module.exports = { … optimization: {
} }minimize: true,minimizer: [new TerserPlugin({parallel: true, // 开启多线程构建,默认值为电脑cpu核数-1compress: true, // 开启压缩mangle: true, // 开启代码丑化...})]
```javascript
// css
// yarn add css-minimizer-webpack-plugin -D 安装依赖
// css代码优化主要为去除空格等
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// ...
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
parallel: true
})
]
}
}
// html
// 通过HtmlWebpackPlugin设置
module.exports = {
...
plugin:[
new HtmlWebpackPlugin({
...
minify:{
minifyCSS:false, // 是否压缩css
collapseWhitespace:false, // 是否折叠空格
removeComments:true // 是否移除注释
}
})
]
}
图片压缩
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
}
},
{
loader: 'image-webpack-loader',
options: {
// 压缩 jpeg 的配置
mozjpeg: {
progressive: true,
quality: 65
},
// 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
optipng: {
enabled: false,
},
// 使用 imagemin-pngquant 压缩 png
pngquant: {
quality: '65-90',
speed: 4
},
// 压缩 gif 的配置
gifsicle: {
interlaced: false,
},
// 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
webp: {
quality: 75
}
}
}
]
},
]
}
文件大小压缩
// yarn add compression-webpack-plugin -D 安装依赖
new ComepressionPlugin({
test:/\.(css|js)$/, // 哪些文件需要压缩
threshold:500, // 设置文件多大开始压缩
minRatio:0.7, // 至少压缩的比例
algorithm:"gzip", // 采用的压缩算法
})
TreeShaking
依赖于ES Module的静态语法分析,消除死代码
- usedExports:通过标记某段代码是否被使用,后使用terser优化
- sideEffects:直接查看该文件时候存在副作用
usedExports
配置
新建app.js,添加方法并导出 ```javascript function app () { console.log(‘app’) }module.exports = { ... optimization:{ usedExports } }
function showAppName () { console.log(‘appName’) }
export { app, showAppName }
在index.js中导入
```javascript
import { app, showAppName } from './app'
window.onload = function () {
console.log('1');
console.log('2');
showAppName();
}
function unusedFn () {
console.log('ha');
}
在开发模式下即mode: development打包,可以看到未被使用的代码被添加了unused harmony export app如下:

此处index.js自身未使用的方法未被添加注释。
再使用生产模式打包,如下:
生产模式打包,未使用的代码被删除。
sideEffects
在package.json中添加sideEffects
"sideEffects": [
"**/*.css",
"**/*.scss",
"./esnext/index.js",
"./esnext/configure.js"
],
sideEffects表示这些文件内容具有副作用,在它们未被引用使用的时候也需要编译打包它们而不是舍弃。
usedExports与sideEffects
它们是两种不同的优化方法。sideEffects更为有效,因为它允许跳过整个模块/文件;usedExports依赖于terser插件对语句副作用的检测。
代码分离
通过splitChunksPlugin来分离代码,默认为☞针对async模块
module.exports = {
...
optimization:{
splitChunks:{
chunks:"all"
}
}
}
内联chunk
使用inlineChunkHtmlPlugin内联一些必须添加的chunk模块
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugin:[
new InlineChunkHtmlPlugin(HtmlWebpackPlugin,[/runtime.+\.js/]
}
