当优化webpack性能时,主要集中在两个方面:优化构建后的结果
和优化构建时的速度
。前一篇文章已经介绍了如何通过webpack的分包
来优化构建后的结果。而在本篇文章中,我们将从减少打包体积
的角度来探讨。
第三方库引入CDN链接
大家都知道CDN是指通过相互连接的网络系统,利用最靠近每个用户的服务器,以更快、更可靠的方式将音乐、图片、视频、应用程序以及其他文件发送给用户,从而实现高性能、可扩展性和低成本的网络内容传递。
平时在开发中我们使用CDN主要有两种方式:
- 将打包的所有静态资源,放到CDN服务器。让用户所有资源都是通过CDN服务器加载。
- 通过利用知名第三方库的CDN,我们可以避免将这些库打包到我们的项目中,从而降低打包体积。
本文的重点是减少打包体积,因此我们将重点讨论第二种方式。
① 首先通过在webpack.config.js
中的配置排除对这些库的打包
js
// webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: resolve(__dirname, 'build'),
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin(
{
template: './index.html'
}
),
],
// 排除打包dayjs
externals: {
lodash: '_',
},
};
强调:在externals这个对象中
lodash
作为属性名(key): 这表示当你在代码中导入lodash
时,实际上不会将lodash
包含在你的输出文件中,而是期望它在运行时从外部引入。'_'
作为属性值(value): 假定在运行环境中已经有一个全局的_
对象或者模块
② 在html模块中,加入第三方库的CDN服务器地址
推荐一个国内比较好用的CDN是 bootcdn
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 导入第三方库的CDN -->
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script></script>
</head>
<body>
</body>
</html>
代码压缩
JS压缩
压缩JavaScripte文件可以使用Terser压缩工具,webpack v5 开箱即带有最新版本的 terser-webpack-plugin
。
在Webpack中,有一个名为
minimizer
属性,它在生产模式下默认使用TerserPlugin
来处理代码。这意味着Webpack会自动使用TerserPlugin
来压缩和优化JavaScript代码,以减小文件大小并提高性能。如果你不满意默认配置,你可以自己创建
TerserPlugin
的实例,并覆盖相关配置。这允许你根据项目的需求自定义代码压缩和优化,使Webpack配置变得灵活而适应各种场景。总之,minimizer
属性允许你控制生产模式下的代码压缩,提供了定制化的选项以满足你的需求。
js
optimization: {
minimize: true,
minimizer: [new TerserPlugin({
extractComments: true,
terserOptions: {
compress:{
ecma: 5, // 设置输出所需的EcmaScript标准版本
unused: false // 是否删除未引用的函数和变量
},
toplevel: true, // 是否在顶级作用域中声明的名称。
keep_classnames: true, // 防止丢失类名,
keep_fnames: true // 防止丢失函数名
}
})],
},
这里面的配置非常多,具体可以看terser文档
CSS压缩
压缩CSS通常是去除无用的空格,压缩CSS可以使用另外一个插件:css-minimizer-webpack-plugin
安装
css-minimizer-webpack-plugin
在optimization.minimizer中配置
js
optimization: {
minimizer: [new cssMinimizerPlugin({
parallel: true
}
)],
},
被压缩后的代码

Tree Shaking
Tree Shaking
,又称为"树摇",是一项用于优化项目打包的技术,其核心目标是在构建过程中自动删除未被引用的函数或变量,从而减小最终生成的文件大小,提高应用程序的性能和加载速度。
JS
usedExports
在生产环境下webpack默认会将
usedExports
设置为true
,在usedExports设置为true时,会有一段注释:unused harmony export mul,这段注释意味着Terser在优化
(上面讲到了Terser
压缩)时,可以删除掉这段代码.所以我们还得讲minimize
设置true
。
js
optimization: {
// 在生产环境下都帮我们配置了
minimize: true,
usedExports: true
}
sideEffects
如果只使用usedExports
会出现一个问题,如下:
以下需要tree Sharking的模块
js
// format.js
export function formatUTC(date) {
return date;
}
export function formatPrice(price) {
return price.toFixed(2);
}
window.effect = "我是一个副作用代码";
以下是主入口文件
js
// main.js
// 由于只对模块进行导入,但是未用到内部函数,按理来说format.js整个模块不应该被打包
import "./utils/format";
console.log("main");
以下是打包后的产物
js
// build/bundle.js
(()=>{"use strict";window.effect="我是一个副作用代码",console.log("main")})();
我们发现window.effect="我是一个副作用代码"
的副作用代码被打包进去了,那么我们应该如何解决这个问题?
可以通过 package.json 的 "sideEffects"
属性,来实现这种方式。
json
// package.json
{
"sideEffects": false,
}
sideEffects设置为false,就是告知webpack可以安全的删除未用到的exports;
如果有一些我们希望保留,可以设置为数组;
json
{
// package.json
"sideEffects": [
// 打包后的文件就不会保留format中的如何代码
"./src/utils/format.js"
],
}
CSS
上述我们学习的都是关于JS的Tree Shaking
,同样我们也要对CSS代码做Tree Shaking
,
CSS的Tree Shaking
需要借助于一些其他的插件purgecss-webpack-plugin
npm install purgecss-webpack-plugin -D
js
// webpack.config.js
new PurgeCSSPlugin({
paths: glob.sync(path.join(__dirname, "src/**/*"), { nodir: true }),
}),
总结
在实际开发中,上述许多配置不需要手动配置(比如:代码压缩
和Tree Sharking
),因为在生产环境下已经默认为我们配置好了。尽管如此,我们仍然需要了解这些配置的原理。