webpack打包优化详解
作者:为了WLB努力
链接:juejin.cn/post/7369485528708317221
顺带吆喝一声,技术大厂,前后端测试捞人。
先简单总结一下,优化Webpack打包可以通过多种方式来提高性能和减小文件大小。以下是一些常见的优化技巧:
-
代码分割(Code Splitting):将代码拆分成多个小块,使得在加载页面时只加载必要的��码。Webpack提供了多种代码分割的方法,如使用
import()
函数、SplitChunksPlugin
插件等。 -
懒加载(Lazy Loading):将不需要立即加载的模块延迟加载,提高页面初次加载速度。通常与代码分割一起使用。
-
压缩代码:使用Webpack的
UglifyJsPlugin
或TerserPlugin
等插件来压缩和混淆JavaScript代码,减小文件大小。 -
优化图片:使用
url-loader
或file-loader
来处理图片,可以将小图片转换为Data URL,或者通过图片压缩工具来减小图片大小。 -
Tree Shaking:通过
Tree Shaking
只打包项目中用到的代码,去除未使用的代码,减小打包体积。确保在Webpack配置中开启了Tree Shaking。注意,webpack5版本的树摇功能比webpack4版本做了很大改进,请升级到webpack5版本哦。 -
模块别名:通过配置Webpack的
resolve.alias
来设置模块别名,减少模块路径的解析时间。
resolve: {// 设置模块如何被解析
alias: {
vue: "vue/dist/vue.esm-bundler.js"
},
extensions: ['.js', '.vue']// 按顺序解析这些后缀名
},
-
提取公共代码:使用
SplitChunksPlugin
或者optimization.splitChunks
来提取公共代码,减少重复加载的代码,优化加载速度。 -
缓存:通过设置
output.filename
和output.chunkFilename
的hash值,使得文件名带有内容哈希,实现文件内容变化时,浏览器能够正确缓存文件。 -
使用
Webpack Bundle Analyzer
:分析打包后的文件,找出体积较大的模块或者文件,针对性进行优化。 -
减少
loader
和plugin
的使用:尽量减少不必要的loader
和plugin
的使用,因为它们会增加打包时间和文件大小。 -
使用
DLLPlugin
:将第三方库单独打包成一个动态链接库(DLL),可以减少每次打包时对第三方库的重新打包,提高打包速度。 -
缩小Webpack搜索范围:通过配置
resolve.modules、resolve.extensions、resolve.mainFields
等参数,缩小Webpack搜索模块的范围,提高打包速度。 -
线上模式
mode: 'production'
和开发环境模式mode : 'development'
要区分设置,并根据不同的环境模式设置不同的devtool
值。
一起来实践吧
1.优化图片
除了用雪碧图和手动压缩图片大小,webpack也可以进一步自动化优化图片, 使用url-loader
或file-loader
处理图片,并且结合image-webpack-loader
来进行图片压缩:
// webpack.config.js
module.exports = {
// 其他配置...
module: {
rules: [
{
test: /.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 小于 8KB 的图片将转换为 base64
name: '[name].[hash:8].[ext]',
outputPath: 'images',
},
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
optipng: {
enabled: false,
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false,
},
webp: {
quality: 75
}
},
},
],
},
],
},
};
2.开启Tree Shaking
确保在Webpack配置中开启Tree Shaking来消除未使用的代码:
// webpack.config.js
module.exports = {
// 其他配置...
optimization: {
usedExports: true,
},
};
3. 提取公共代码,进一步分包
module.exports = {
optimization: {
minimizer: [new ESBuildPlugin()],
splitChunks: {
chunks: 'all', // 将所有类型的 chunks 进行分割,包括同步和异步的
minSize: 10000, // 模块最小体积,将最小包体积降低到 10KB,以利用 HTTP/2 并行请求
minRemainingSize: 0,
minChunks: 1, // 模块最小被引用次数
maxAsyncRequests: 30, // 按需加载时的最大并行请求数
maxInitialRequests: 30, // 入口点的最大并行请求数
enforceSizeThreshold: 50000, // 强制执行拆分的体积阈值
automaticNameDelimiter: '~', // 文件名的连接符
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
这段配置使用了Webpack 5中的 optimization
选项,并结合了 ESBuildPlugin
进行代码压缩。同时,使用了 splitChunks
选项来进一步优化打包结果。
-
minimizer: [new ESBuildPlugin()]
:这里使用了ESBuildPlugin
来进行代码压缩,它能够利用 ESBuild 引擎提供的快速压缩功能,提高构建效率。 -
splitChunks
:这个选项用于配置代码分割。在这个配置中,有两个cacheGroups
,分别是defaultVendors
和common
。-
defaultVendors
:用于提取第三方库,它的test
属性指定了匹配node_modules
中的模块。priority
设置了优先级,值越大,优先级越高。 -
minChunks: 2
表示模块被引用至少两次时才会被提取。reuseExistingChunk: true
表示如果一个模块已经被提取过了,就会复用已经存在的模块,而不是再次创建一个新的模块。
-
-
设置合理的分包阈值
通过设置合理的 minSize
和 maxSize
来控制包的大小,避免包太小导致请求次数增加或包太大导致加载时间过长:
module.exports = {
optimization: {
splitChunks: {
minSize: 30000, // 最小包体积,根据具体情况测试分析,具体值以实际调试为准
maxSize: 250000, // 最大包体积,根据具体情况测试分析,具体值以实际调试为准
},
},
};
这个配置能够有效地将第三方库和共享模块分割成独立的文件,以便利用浏览器的并行加载能力,提高应用的加载速度和性能。
4. 严格区分打包环境
在Webpack中,Source Map(源映射)是一种文件,它将编译后的代码映射回原始源代码。这对于调试和定位问题非常有用,因为它允许你在浏览器开发者工具中直接查看原始代码,而不是查看编译后的代码。Webpack支持多种类型的Source Map,你可以根据需求选择合适的类型。以下是一些常见的Source Map配置选项:
-
eval: 将Source Map作为 DataURL嵌入到打包后的JavaScript文件中,不会生成额外的文件,但会增加打包时间。
-
source-map: 生成单独的Source Map文件,以
.map
为后缀,对调试信息不作修改。 -
cheap-source-map: 生成单独的Source Map文件,但不包含列信息,对调试信息进行简化,提高构建速度。
-
cheap-module-source-map: 类似于
cheap-source-map
,同时对loader的Source Map也进行了处理,以便更好地定位到源代码中的错误位置。 -
inline-source-map: 将Source Map数据以DataURL的形式嵌入到打包后的JavaScript文件中,不会生成额外的文件,但会增加打包体积。
-
hidden-source-map: 生成单独的Source Map文件,但不在打包后的JavaScript文件中引用它,只在构建过程中用于调试。
-
nosources-source-map: 生成单独的Source Map文件,但不包含源代码内容,用于发布生产环境版本。
你可以通过在Webpack配置文件中设置devtool
选项来配置Source Map类型。例如:
module.exports = {
// 其他配置...
devtool: 'source-map',
};
如果你需要在生产环境中生成Source Map,通常建议使用hidden-source-map
、nosources-source-map
等选项,以确保源代码的安全性,并减小打包体积。而在开发环境中,可以选择更详细的Source Map类型,以方便调试和定位问题。
5.充分利用webpack5的持久化缓存(Persistent Caching)
Webpack 5 提供了一些缓存优化的功能,可以显著提高构建性能。以下是一些Webpack 5 中的缓存优化方式:
5.1. 持久化缓存(Persistent Caching)
Webpack 5 引入了持久化缓存,可以将构建过程中生成的缓存结果保存到磁盘上,以便下次构建时直接使用缓存,而不需要重新构建所有模块。这可以通过在配置文件中添加 cache.type
和 cache.buildDependencies
选项来实现:
module.exports = {
// 其他配置...
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename],
},
},
};
5.2. 并行构建(Parallelism)
Webpack 5 支持并行构建,可以同时处理多个构建任务,提高构建速度。你可以通过在配置文件中添加 parallel
选项来启用并行构建:
module.exports = {
// 其他配置...
parallelism: 4, // 同时处理的任务数量
};
5.3. 缓存组件(Caching Modules)
Webpack 5 使用 moduleIds
来标识模块,并且默认情况下会对模块的导出进行 hash 编码。你可以使用 optimization.moduleIds
选项来自定义模块标识的生成方式:
module.exports = {
// 其他配置...
optimization: {
moduleIds: 'deterministic', // 可选值: 'deterministic', 'size', 'total-size', 'hashed'
},
};
5.4. 模块缓存(Module Cache)
Webpack 5 支持模块级别的缓存,可以将经常引用的模块缓存起来,提高构建速度。你可以通过在配置文件中添加 cache
选项来启用模块缓存:
module.exports = {
// 其他配置...
cache: {
type: 'filesystem', // 持久化缓存
cacheDirectory: path.resolve(__dirname, '.webpack_cache'), // 缓存目录
},
};
通过使用这些缓存优化功能,Webpack 5 可以显著提高构建性能,尤其是对于大型项目和复杂项目来说,优化效果更加明显。
- 点赞
- 收藏
- 关注作者
评论(0)