
背景
上一篇文章我们分析了:为什么 esbuild 这么快
还有数据对比:
可以明显看到:
esbuild
一骑绝尘, 以绝对优势领先。
看看最下面, 赫然是我们最熟悉的
webpack
。
那么,
webpack 的构建为什么慢呢?到底慢在哪呢 ?
下面是我的一些思考,分享给大家,希望对大家有所帮助。
正文
首先我们先看一下 webpack 构建的大致流程:
webpack build flow
流程走的比较长。
那么,整个流程的
性能瓶颈
在哪里呢?
我认为主要是在以下两个阶段:
-
代码构建
-
代码压缩
https://www.quora.com/What-is-Webpack-and-babel-loader
我们分别来看。
1. 代码构建
代码构建阶段, 需要做的一个很重要的事情是
模块依赖分析
, 生成
Module Graph
。
这部分有十分复杂的流程。
webpack build graph
https://medium.com/webpack/the-chunk-graph-algorithm-week-26-29-7c88aa5e4b4e
这部分非常复杂,也比较耗时。
为此 webpack 也设计了对应的的
算法
去优化这部分,感兴趣的可以去研究一下。
这部分的详细解析,有个视频讲的不错,感兴趣的可以去看一下:
https://youtu.be/Lzh8A0p3z8g
说回构建。
现代浏览器对
esm
支持的越来越好,模块依赖分析的工作,浏览器就能完成。
而且, 浏览器的很多包分析工具是用
C/C++
写的, 显然是要比
webpack
使用
js
去分析整个
依赖图谱
更具优势,速度上也是要快很多的。
2. 代码压缩
目前最成熟的 js 压缩工具是
UglifyJS
。
它会分析 js 的
代码语法树
, 理解代码含义,从而能做到诸如: 去掉无效代码,去掉日志输出代码,缩短变量名等优化。
webpack 使用
压缩插件
来完成这部分工作。
其中:
webpack
使用的
terser
, 是用
js
写的, 源自于最早的
uglyfy.js
, 功能很丰富, 但是速度非常非常慢。
这点, 也是 webpack 速度慢的原因之一。
不过在代码压缩方面,
vite
选择的也是
Terser
。
对此,文档中有相关描述:
- build.minify:
- 类型:boolean | 'terser' | 'esbuild'
- 默认:'terser'
设置为
false
可以禁用最小化混淆,或是用来指定使用哪种混淆器。
默认为
Terser
。
虽然
Terser
相对
较慢
,但大多数情况下构建后的
文件体积更小
。
ESbuild 最小化混淆
更快
, 但构建后的文件
相对更大
。
更多信息可以参考:https://cn.vitejs.dev/config/#build-minify
另外,如果你有留意, 就会发现一个现象:
- Esbuild, 使用
写的。GO
- SWC, 是用
写的。Rust
都不是用
js
写的。
未来前端的编译工具,大概也会往这个方向走, 要么用
Go
写, 要么用
Rust
写,而不是把这种能形成
性能瓶颈
的东西用
js
来实现。
还有一点需要提一下。
在文章开头的图中, 看起来 webpack5 的速度比 webpack4 要慢:
但这
不代表
webpack 5 不好,大家不要误会啊。
webpack 5
里面 做了
大量的优化
,
甩掉了不少历史包袱
。
有一些
新特性
还有
非常有用
的, 比如:
-
Module Federation
-
Real Content Hash
不难想到,
webpack
团队还是做出了很多努力的, ❤️ 。
总结
这篇文章, 是半夜突然有了思路, 花了两个小时写出来。
分享给大家,希望对大家有所启发, 谢谢。