Bun bundler 实现依赖预打包

image.png

调研 Bun bundler 实现依赖预打包。Bun 还未发布正式版本,bun bundler 现在还在 beta 阶段,为啥选用 bun 打包?

看了下官方文档,bun build 配置非常简单,无法解决业务工程复杂工程化问题。而且 target 仅支持 browserbunnode 三个值,format 暂时只有 esm(后续计划支持 cjsiife),这样如果 bun 打包业务工程,产物兼容性会有很大问题。另外,bun 作为一个新的打包器,产物稳定性无法与 Webpack、Rollup 相比。

虽然 bun 不能用于打包业务工程,但是有几个场景可以考虑:

  • 业务工程本地 dev;
  • 打包组件库;
  • 打包一些 node 依赖。

为啥以上场景可以用 bun,因为这些场景打包产物并不直接部署,比如打包组件库,输出 esm 格式完全没问题,兼容性也可以在业务工程构建的时候进行处理,再比如打包 node 依赖,这些一般都是 devDependencies,对兼容性没有那么敏感,同时如果产物质量有问题,一般本地跑就能提前发现了,最坏情况就是 CI 构建报错,对用户侧来说不会有影响。

下面来谈谈 bun 打包 node 依赖有啥好处。如果用过 UmiJS 或者 Next.js,对依赖预打包这个概念应该都很熟悉。为了解决第三方库间接依赖不受控问题,进而导致一些潜在的 npm 供应链攻击问题,解法就是依赖预打包,收敛 npm 依赖层级。核心思想就是交给中间商锁定依赖,并对此负责,定期更新。

依赖预打包还可以显著提升 Node CLI 应用启动性能。我们知道,在 Node 里面 require() 是非常昂贵的,存在大量 IO 操作,如果分析一下火焰图,实际上 Node CLI 应用运行大部分时间都在做模块加载。如果将 Node 应用提前打包为单文件,则可以避免运行时 require() 开销(另一种优化策略是按需 require(),将 require() 延迟到需要的时候再去加载)。

如何做依赖预打包,Next.js 和 UmiJS 的做法是用 ncc 打包(内部封装了 Webpack,用 target: "node" 打包),当然也可以用 father-build 打包(底层实际上也是 Webpack)。考虑到依赖更新问题,依赖预打包可能是高频操作,整体构建速度会影响开发效率。我们可以看下 Next.js 仓库,预打包依赖有数百个,无论本地 dev 还是 CI build、发包,都要跑一遍依赖预打包。显然,用更快速的打包器可以极大提升开发效率。

从 bun 官方文档可以看到,打包 10 份 Three.js 作为基准测试,bun 仅需 0.17s,甚至比 esbuild 还要快(大家可以本地跑一下,几乎在敲命令的瞬间,bun 就已经打包完了):

Pasted image 20230524150431.png

安装:

$ brew tap oven-sh/bun # for macOS and Linux
$ brew install bun

更新:

$ brew upgrade bun

依赖预打包:

$ bun build webpack 
	--outdir ./compiled 
	--entry-naming "webpack/[name].[ext]" 
	--target node --minify 
	--external pnpapi 
	--external uglify-js 
	--external @swc/core 
	--external esbuild

# 本人 M1 Pro 机器,全量打包一份 Webpack 仅需 68ms
[68ms] bundle 867 modules

可以看出,bun 确实非常快,几乎在敲命令的瞬间就打包完了,性能提升巨大。

另外还推荐尝试一下 bun runbunx,极快。平时我们跑 npm scripts,一般会用 npm run、yarn run、pnpm run 等等,需要注意,这些 runner 启动也是有开销的,而且都比较慢,而 bun run 跑 npm scripts 启动速度极快,体验非常丝滑。

体验过 bun 之后,个人建议 Vite 可以放弃维护了。Vite 4.3 没有新功能,只是更快,几乎已经榨干了 JS 代码的性能,而且还是在降低代码语义性、可维护性的情况下,后续应该很难有进一步提升空间了。Vite 4.3感觉和 patak 大佬观点背道而驰,当初选用 JS 为了让前端开发者更容易维护,结果现在却牺牲维护性换取性能。其实我个人觉得,选用 Go 语言也不错,容易上手(对前端友好,同样是 FP 编程风格),而且性能又好。

参考:

bun.sh/blog/bun-bu…

shaneosullivan.wordpress.com/2023/05/17/…