Esbuild vs Babel
前言
最近在做等create-react-app-webpack5
官方支持的同时, 去研究了一下最近新出的一些打包工具, 如vite/snowpack
, 发现了一些他们各自的优缺点, 在此总结一下
打包工具
webpack
webpack
就不用过多介绍了, 完善的生态和插件系统, 各工具链必须要支持的框架, 基本满足所有需求, webpack5
的本地缓存机制出现后也极大的提高了开发体验
snowpack
相比起webpack
来说, 主要优化了bundle
构建的过程, 不再将所有依赖内容打包压缩到bundle.js
中, 而是拆分成各自的小文件, 这样达到O(1)
的构建速度, 贴个官方的对比图
但缺点也是很明显的: 社区支持不够, 各插件的整合程度不强, 如果需要用一些新功能需要自己采坑, 可能会比较困难. 而且还有个比较严肃的问题: 这种在开发期分离打包的做法, 会导致开发期和生产环境代码不一致, 风险很大. 所以在尝试了一下react-demo
后, 暂时先搁置
vite
vite
是最近两年的热门打包工具之一, 也有受到snowpack
启发和影响, 同样是开发期通过es-modules
加载依赖库, 但有更好的官方支持和社区环境, 以及一个比较大的新特性: 使用了esbuild
来打包js
代码
按照官方文档初始化了一个react
项目后, 确实有了丝滑的开发体验, 打包速度也是非常快, 但同样存在开发期和打包生产环境内容不一致的问题, 而且polyfill
都需要自己引用解决, 在正式项目上还是不太方便使用
esbuild
虽然vite
并不太适合现在的react
项目开发, 但是里面的esbuild
却是个非常好的工具, 其实在webpack
中也是可以使用esbuild
来打包的
esbuild-loader
esbuild
可以简单的理解为: 使用go
语言开发的babel
编译器
在webpack
中使用也非常简单: 直接用esbuild-loader
替换掉babel-loader
即可
这里直接简单粗暴的通过索引替换掉babel-loader
, 如果要生产环境使用可以使用find
和filter
查询到索引后替换
1 | config.module.rules[1].oneOf[3].loader = require.resolve('esbuild-loader'); |
替换完成后, 执行npm start
, 在webpack5
的加持下可以做到10s
内启动完成, 相比起使用babel-loader
的25s
来说, 提高了大约150%
的构建速度, 同时, 也不存在vite/snowpack
的开发环境和生产环境代码不一致的问题, 看起来是个比较好的选择
问题
虽然esbuild
极大的提高了编译速度, 但是存在一个硬伤: 暂时还不支持插件, 这意味着无法自定义或者按需修改编译内容. 而现在很多工具链都是依赖babel-plugin
来实现各自的功能的.
styled-jsx
比如常用的styled-jsx
, 是通过[babel-plugin]styled-jsx/babel
插件来实现的自定义解析jsx
, 以及现在支持的babel-macro
也需要使用babel-plugin-macros
. 使用esbuild
的情况下, 就完全无法使用styled-jsx
了
在rollup
中的babel
插件也是同样可以支持styled-jsx
的, 但vite
虽然使用的rollup
, 但由于同样使用esbuild
, 所以无法支持styled-jsx
istanbul
其次是代码覆盖率插件, 上个月研究的cypress
的代码覆盖率生成, 是依赖babel-plugin-istanbul
注入代码调用埋点的, 在esbuild
打包时没有办法注入, 所以也就没有办法获取覆盖率了
结论
兜兜转转饶了一圈, 结果还是回归原始的webpack+babel
老套路了. 虽然前端工程迭代足够快, 但想达到更高的高度, 还是需要时间沉淀优化的
Esbuild vs Babel