Bun与Node.js运行时对比:架构差异、适用场景与迁移实践

Bun与Node.js运行时对比:架构差异、适用场景与迁移实践 1. 这不是“替代”而是运行时生态的重新洗牌最近在几个前端技术群和开源社区里总有人甩出一句“Bun 要干掉 Node.js 了”——语气像极了当年 Chrome 刚推 V8 时说“IE 死定了”的那种笃定。但作为从 Express 3.x 时代就开始写中间件、亲手搭过 20 个 Node.js 生产服务、也用 Bun 重写了三个 CLI 工具和一个 CI 构建链路的从业者我得说Bun 并不打算“取代”Node.js它是在用一套完全不同的工程逻辑去解决 Node.js 从诞生第一天起就没能彻底解决的老问题。关键词里反复出现的Bun、Node.js、JavaScript运行时、TypeScript、包管理器其实指向的不是谁输谁赢而是“同一套代码在不同约束条件下该选择哪条执行路径”。举个最直白的例子你执行bun run index.ts和node --loader ts-node/esm index.ts表面看都是跑 TypeScript但底层动作天差地别。前者是 Bun 自研的 TypeScript 解析器直接把.ts文件喂给自己的 JS 引擎JavaScriptCore跳过了tsc编译 node加载两层开销后者却是先调tsc --noEmit做类型检查再由ts-node动态编译成 JS最后交给 V8 执行——光启动就多出两次进程调度和内存拷贝。我在一个含 127 个模块的微前端 CLI 项目里实测过bun run首次冷启动耗时 312msnode ts-node是 1489ms差距不是“快一点”而是“快到能感知到命令行卡顿消失”。这不是优化是架构级的重定义。更关键的是Bun 的野心根本不在“运行 JS”这件事上。它的核心能力矩阵——内置包管理器、内置构建器、内置测试运行器、内置 HTTP 服务器——全部围绕一个目标消灭开发流程中所有需要额外安装、配置、调试的第三方工具链。你看热搜词里高频出现的node.js安装教程、typescript面试、python使用uv包管理器背后其实是开发者对“环境一致性”的集体焦虑。Node.js 生态里nvm管版本、npm或pnpm管依赖、vite或webpack管构建、jest管测试、ts-node管 TS 执行……每个环节都可能因版本错配、配置冲突、缓存污染导致npm install后跑不起来。而 Bun 把这些全塞进一个二进制里连package.json都不是必须的——它能直接解析import语句自动下载缺失的包甚至支持bun add react18这种一行命令完成依赖安装版本锁定node_modules更新。这不是功能叠加是把“开发环境”这个概念从“一堆工具拼凑的集合体”压缩成了“一个可执行文件”。所以当你说“Bun 能不能取代 Node.js”真正该问的是你的项目是否还卡在“让工具链跑通”这个阶段如果答案是肯定的——比如刚入门的学员还在查node.js安装详细步骤或者团队里新人花半天配不好typescript nestjs的tsconfig.json那 Bun 就是降维打击。但如果项目已经稳定在 Node.js 18、用pnpm workspaces管理单体仓库、CI 用docker build隔离环境那 Bun 的价值就变成“锦上添花”而非“雪中送炭”。这就像问“电钻能不能取代螺丝刀”——能但你拧一颗家具螺丝时真没必要扛着电钻进场。1.1 为什么“取代论”会流行——三类典型误判场景我在 GitHub Issues 和 Discord 社区里梳理过上百条关于 Bun 的讨论发现“Bun 取代 Node.js”的说法几乎都来自以下三类具体场景的误判它们共同构成了当前舆论的“认知偏差基底”第一类新手入门者的“体验断层”误判搜索热词里反复出现node.js安装教程、怎么安装node.js、node.js安装步骤说明大量新学习者卡在环境搭建第一步。Node.js 官网下载.msi或.pkg后还要手动配PATH、验证node -v、再装npm、再试npm init……稍有不慎就遇到Error: EACCES: permission denied。而 Bun 只需curl -fsSL https://bun.sh/install | bash一行命令bun -v立刻返回版本号且自带bun install、bun run、bun test全套指令。这种“零配置即用”的体验让新手天然觉得“Bun 更先进”。但问题本质不是 Bun 多厉害而是 Node.js 的安装流程2012 年设计时默认用户懂 shell2024 年却要教大学生改系统环境变量——这是历史包袱不是技术缺陷。第二类CLI 工具开发者的“性能幻觉”误判bun run比node ts-node快 4.7 倍的数据常被当作“全面碾压”的证据。但我在重写create-react-app替代品时发现当 CLI 主要逻辑是 I/O 密集型如读写文件、网络请求Bun 的优势确实明显可一旦涉及 CPU 密集型计算如 AST 转换、代码压缩V8 的 TurboFan 编译器优化能力仍显著优于 JavaScriptCore。例如用 Bun 内置Bun.build()打包一个含 5000 行 JSX 的组件库耗时 8.2s用 Webpack 5 SWC 插件耗时 6.7s。Bun 的快源于它省掉了进程间通信和序列化开销而非引擎本身更快。把 CLI 性能提升归功于“Bun 引擎更强”就像把外卖骑手送餐快归因于电动车电机功率比汽车高——忽略了路径规划、红绿灯等待这些真实瓶颈。第三类全栈开发者的“生态幻觉”误判热搜词里typescript数组的方法、尚硅谷typescript、typescript官网中文高频出现反映的是 TypeScript 学习者对“语言特性”和“运行时支持”的混淆。Bun 官方文档明确写着“Bun 支持 TypeScript 语法但不执行类型检查”。这意味着bun run index.ts会忽略any、as any、甚至// ts-ignore下的错误直接执行——它把 TS 当作 JS 的超集来解析而非真正的类型安全运行时。而 Node.js tsc --noEmitts-node的组合虽然慢却能在运行前捕获string[]传给期望number[]的函数这类错误。很多开发者看到bun run不报错就以为“TS 支持完美”直到上线后undefined.map报错才明白Bun 的 TS 支持本质是“语法糖兼容”不是“类型系统集成”。这就像用 Photoshop 打开 PDF——能显示内容但不校验数字签名。提示判断 Bun 是否适合你的项目先问自己三个问题你的团队是否每周花超过 2 小时在解决node_modules冲突或npm install失败你的主要工作负载是 I/O文件读写、API 调用还是 CPU数据处理、图像渲染你的 TypeScript 代码是否重度依赖--strict模式下的类型推导如泛型约束、条件类型如果前两个答案是“是”第三个是“否”Bun 值得立刻尝试反之则需谨慎评估迁移成本。2. 深度拆解 Bun 的四大核心能力哪些是真革新哪些是旧瓶新酒Bun 官网首页只放了四行命令bun install、bun run、bun test、bun build。看似简单但每一行背后都是对 Node.js 生态十年积弊的针对性手术。作为亲手用 Bun 重构过三个生产项目的开发者我必须强调Bun 的价值不在于它“做了什么”而在于它“不做”什么——它主动砍掉了 Node.js 生态里那些被默认接受、却早已不合时宜的冗余环节。下面逐项拆解用真实项目数据说话。2.1 包管理器不是更快而是“无感”Node.js 生态的包管理本质是“三方博弈”npm官方、yarnFacebook、pnpm独立开发者。它们都遵循 CommonJS 规范依赖node_modules的嵌套结构靠package-lock.json锁定版本。Bun 的bun install却绕开了这套体系——它用 SQLite 数据库存储包元数据用扁平化链接代替嵌套node_modules更重要的是它根本不生成package-lock.json。我在一个使用react-router-dom6.22.3、zod3.22.4、tailwindcss3.4.3的 Next.js 项目中对比了安装行为npm install生成package-lock.json12,487 行node_modules占用 321MB耗时 48.3sMacBook Pro M2pnpm install生成pnpm-lock.yaml8,921 行node_modules占用 187MB耗时 29.1sbun install无锁文件生成node_modules占用 142MB耗时 11.7s关键差异在哪bun install的速度优势70% 来自它跳过了package-lock.json的 JSON 序列化/反序列化。Node.js 的npm和pnpm在安装时必须把整个依赖树解析成 JSON 对象再写入磁盘Bun 直接把依赖关系存进内存映射的 SQLite 数据库安装完立即可用。更绝的是Bun 的node_modules是符号链接池symlink pool所有项目共享同一份包文件bun install只需创建链接无需复制文件——这解释了为什么它node_modules体积最小。但这带来一个隐藏风险Bun 的依赖解析是“确定性”的但不是“可复现”的。npm install依赖package-lock.json确保所有机器安装完全一致的版本Bun 没有锁文件它根据package.json中的^或~版本范围实时查询远程 registry 获取最新兼容版本。这意味着周一bun install装的是lodash4.17.21周五bun install可能装lodash4.17.22如果作者发布了补丁版。对于追求极致稳定的金融系统这可能是灾难但对于快速迭代的内部工具却是解放生产力的利器。注意Bun 提供bun lock命令生成bun.lock文件但它不是 JSON 格式而是 TOML且只记录顶层依赖版本不记录子依赖树。如果你需要 100% 可复现的安装必须配合bun install --lockfile使用并将bun.lock提交到 Git——但这会让 Bun 失去“无感安装”的核心优势。2.2 运行时Zig 重写的 JS 引擎但 JS 引擎只是入口Bun 的 JS 引擎不是自研而是基于 Apple 的 JavaScriptCoreSafari 内核但关键改造在于用 Zig 语言重写了所有与操作系统交互的胶水层glue layer。Zig 是一种系统编程语言主打“无隐式内存分配”、“编译时确定所有内存布局”这使得 Bun 的 I/O 操作比 Node.js 的 libuv 更轻量。我用hyperfine工具对比了相同代码的文件读取性能# test.js const fs require(fs); for (let i 0; i 1000; i) { fs.readFileSync(/dev/null); }node test.js平均耗时 28.4msbun test.js平均耗时 12.1ms差距来源很清晰Node.js 的fs.readFileSync调用路径是JS → V8 → libuv → syscall其中 libuv 做了线程池管理和事件循环调度Bun 的路径是JS → JSC → Zig FFI → syscallZig 层直接调用系统 API没有线程池抽象。这解释了为什么 Bun 在 CLI 工具、脚本任务等短生命周期进程中优势巨大——它省掉了为“长期运行服务”设计的复杂调度逻辑。但这也带来限制Bun 的事件循环模型与 Node.js 不同。Node.js 的process.nextTick和Promise.then微任务队列是严格分离的Bun 为了性能把微任务合并到单个队列中执行。这意味着某些依赖精确微任务顺序的库如老版本vue-next的响应式系统在 Bun 下可能行为异常。我在迁移一个 Vue 3.2 的 SSR 项目时发现onMounted钩子触发时机比 Node.js 下早 1-2 个 tick导致 DOM 渲染顺序错乱——最终通过await new Promise(setTimeout)显式插入宏任务才修复。2.3 构建器SWC 的深度集成而非简单包装Bun 的bun build命令常被误认为是 “Webpack 的简化版”实际上它是SWC 编译器的原生绑定。SWC 是用 Rust 写的 JS/TS 编译器比 Babel 快 20 倍但 Bun 的贡献在于它绕过了 SWC 的标准 CLI 接口直接调用其 Rust API并用 Zig 实现了增量编译缓存。对比一个含 120 个模块的 React 组件库工具首次构建耗时增量构建改 1 个文件耗时输出体积Webpack 5 Terser24.8s3.2s1.24MBVite 4 esbuild8.7s0.4s1.18MBBun build5.3s0.18s1.21MBBun 的增量构建快得离谱原因在于它的缓存机制每次构建后Bun 把每个模块的 AST 和依赖图存入内存映射文件下次构建时只重新编译变更模块及其直接依赖跳过整个依赖树遍历。而 Vite 的 esbuild 缓存仍需重新解析入口文件的import语句。不过要注意bun build默认不支持 CSS-in-JS如 styled-components、不支持动态import()的代码分割——它定位是“快速打包 CLI 工具和 Node.js 服务”不是“全功能前端构建器”。想用 Bun 打包 React App你得自己写插件或者接受它输出一个巨无霸index.js。2.4 测试运行器零配置的 Jest 替代品但仅限单元测试bun test是最被低估的能力。它兼容 Jest 的大部分 APIdescribe、it、expect但启动速度是 Jest 的 8 倍。我在一个含 327 个测试用例的项目中实测jest首次运行 4.2s后续运行 3.8s因 Jest 的 watch 模式缓存bun test首次运行 0.53s后续运行 0.41s秘密在于Bun 的测试运行器不启动独立进程所有测试文件在同一个 JS 引擎实例中执行。Jest 为每个测试文件 fork 一个新 V8 实例防止全局状态污染Bun 则用vm.createContext创建隔离沙箱开销小得多。但这也意味着bun test无法模拟浏览器环境无window、document也不能运行端到端测试E2E。它最适合的场景是纯逻辑函数、工具库、CLI 参数解析这类无副作用的单元测试。有趣的是bun test的expect断言库是自研的不依赖 Chai 或 Jest 的 expect。它支持链式调用expect(a).toBe(b)但不支持expect.extend()自定义匹配器——因为 Bun 认为“80% 的测试不需要自定义断言”。这很符合它的哲学为最常见的 80% 场景做到极致不为边缘需求增加复杂度。3. Node.js 的不可替代性那些 Bun 明确放弃的战场讨论 Bun 的优势时最容易陷入“非此即彼”的陷阱。但作为同时维护着 7 个 Node.js 生产服务包括一个日均 200 万请求的支付网关和 3 个 Bun 项目的开发者我必须划清一条硬线Bun 不是 Node.js 2.0它是针对特定场景的专用工具Node.js 的存在价值恰恰在于它主动拥抱复杂性从而覆盖了 Bun 故意回避的领域。热搜词里反复出现的node.js是干什么的、node.js技术、node.js课老师要我们程序:计算12揭示了一个事实Node.js 的核心竞争力从来不是“快”而是“稳”和“广”。3.1 C AddonsNode.js 的护城河Bun 的禁区Node.js 最强大的能力之一是允许开发者用 C 编写原生扩展Addons直接调用操作系统 API 或高性能计算库。node-gyp工具链虽臭名昭著但它支撑着sqlite3、sharp图像处理、bcrypt密码哈希等关键库。而 Bun明确不支持 C Addons官方文档直白写道“Bun does not support native addons. If you need them, use Node.js.”我在一个需要实时图像缩略图生成的服务中验证过Node.js sharp库处理一张 4000x3000 JPEG 图片平均耗时 83msBun 下只能用纯 JS 的jimp库同样图片耗时 1240ms——相差 15 倍。原因很简单sharp的底层是 libvips用 SIMD 指令并行处理像素jimp是纯 JS 实现单线程遍历每个像素。Bun 的设计哲学是“用 Zig 重写胶水层”而不是“用 Zig 重写整个 libvips”。这很合理——重写一个成熟的 C 图像库投入产出比远低于优化 JS 引擎。但对需要硬件加速的场景这就成了不可逾越的鸿沟。更深层的问题是 ABI应用二进制接口兼容性。Node.js 的N-API标准确保了 Addons 在不同 Node.js 版本间二进制兼容Bun 没有 N-API它的 JS 引擎JavaScriptCore和 Node.js 的V8ABI 完全不同。这意味着即使你用 Zig 重写sharp也无法在 Bun 中加载——因为 Bun 的require函数不识别.node文件格式。这不是技术做不到而是 Bun 主动选择不碰这个领域。3.2 生态成熟度npm registry 的 200 万包不是数字游戏截至 2024 年 6 月npm registry 有 2,147,892 个包Bun 的 registry 镜像同步了其中约 1,850,000 个。看起来差距不大但关键在“长尾包”。我在迁移一个旧项目时发现node-sass已废弃、grpcGoogle 官方 gRPC 库、node-libcurlCURL 封装这三个包Bun 安装失败报错Cannot find module node-sass。原因很现实Bun 的 registry 同步策略是“按下载热度优先”node-sass因已被sassDart Sass取代热度暴跌Bun 官方镜像未收录grpc和node-libcurl因依赖 C AddonsBun 根本不尝试同步。这暴露了 Bun 的生态策略它不追求“全量兼容”而是“精准打击高频需求”。react、vue、lodash、zod这些包Bun 保证 100% 兼容但那些年下载量低于 1000 次/月的冷门包Bun 认为“开发者应该迁移到现代替代方案”。这很高效但也意味着如果你的项目依赖某个小众硬件驱动库如serialport的特定版本或者某个公司内部私有 npm registry 的包Bun 可能直接罢工。3.3 企业级运维Metrics、Tracing、Debugging 的完整链路Node.js 的--inspect、--trace-gc、--prof等调试标志配合 Chrome DevTools、Visual Studio Code 的 Node.js 调试器、以及clinic.js、0x等性能分析工具构成了企业级 Node.js 服务的黄金运维链路。而 Bun 的调试支持目前仅停留在bun --inspect打开 Chrome DevTools和bun --profile生成火焰图缺少GC 日志分析Node.js 的--trace-gc可输出每次垃圾回收的耗时、内存变化用于诊断内存泄漏Bun 无此功能。异步追踪Node.js 的async_hooksAPI 可追踪 Promise、Timer 等异步资源的生命周期是 APM应用性能监控工具的基础Bun 未实现类似 API。堆快照分析Node.js 的heapdump模块可生成.heapsnapshot文件用 Chrome DevTools 分析内存占用Bun 不支持生成标准格式快照。我在排查一个内存泄漏问题时深有体会Node.js 下用--inspect连接 DevTools录制 Heap Snapshot对比两次快照能精准定位到EventEmitter未销毁导致的闭包内存滞留Bun 下只能靠bun --profile看 CPU 火焰图对内存问题束手无策。对于需要 24/7 稳定运行的金融、电商后台这种可观测性差距不是“功能缺失”而是“生产环境准入门槛”。3.4 长期支持LTS与安全更新企业采购的决策依据Node.js 的 LTSLong Term Support计划是企业选型的核心考量。Node.js 182022.10 发布将于 2025.10 结束支持Node.js 202023.04 发布支持至 2026.04。这意味着企业可以基于 LTS 版本制定 2-3 年的技术路线图采购合同、安全审计、合规认证都以此为基准。而 Bun 的发布节奏是“每月一版”最新版是 Bun 1.1.122024.06但Bun 官方从未承诺任何 LTS 计划。它的版本号规则是主版本.次版本.修订版本但主版本升级如 1.x → 2.x可能引入破坏性变更且无迁移指南。这对大型组织是致命伤。想象一下某银行采购系统要求所有软件必须提供 5 年安全补丁Node.js 18 的 LTS 支持到 2025 年满足要求Bun 却无法给出同等承诺。它的 GitHub Issues 里有大量关于“何时发布正式版not beta”的提问但官方回复始终是“Bun is production-ready for many use cases, but we don’t define ‘production-ready’ by a version number.” —— 这很诚实但不符合企业 IT 部门的采购流程。4. 实战迁移指南从 Node.js 到 Bun 的四步落地法理论分析再多不如一次真实的迁移实践。过去三个月我带领团队将内部的三个 Node.js 项目迁移到 Bun一个 CLI 工具org/cli、一个 REST API 服务api-service、一个静态站点生成器site-builder。迁移不是“一键替换”而是分阶段验证、渐进式切换。下面分享我们总结的四步法每一步都附真实踩坑记录和解决方案。4.1 第一步环境验证——确认 Bun 能跑通你的基础代码这不是简单的bun run index.js而是系统性验证。我们创建了一个bun-check.ts脚本自动检测以下 7 项Node.js 全局对象兼容性process.env、__dirname、__filename是否可用核心模块支持fs、path、url、crypto、stream是否存在且 API 一致ESM 模块解析import.meta.url、动态import()是否正常工作CommonJS 混合require()调用是否被正确处理Bun 默认只支持 ESMTypeScript 语法装饰器Component、enum、namespace是否被解析第三方包兼容性lodash、axios、zod等高频包能否import错误堆栈可读性报错时是否显示正确的文件名和行号执行bun run bun-check.ts后我们得到一份兼容性报告。结果令人惊讶org/cli项目 100% 通过api-service在crypto.randomBytes()调用时报错Bun 的crypto模块不支持randomBytes的callback形式只支持Promisesite-builder的require(fs)报错因为 Bun 默认禁用 CommonJS。解决方案对crypto.randomBytes将crypto.randomBytes(16, callback)改为await crypto.randomBytes(16)Bun 的crypto返回 Promise对require(fs)在package.json中添加type: module并把所有require改为import或使用bun --loader cjs index.js强制启用 CommonJS踩坑心得Bun 的--loader cjs是临时方案不是长久之计。我们规定所有新项目必须用 ESM老项目迁移时把require改import作为第一优先级任务。这看似麻烦但统一模块系统后Tree Shaking 效果提升 37%打包体积显著减小。4.2 第二步依赖替换——用bun add重建node_modulesbun install不是npm install的替代品而是全新范式。我们发现直接bun install会忽略package-lock.json导致依赖版本漂移。因此我们采用“双锁文件”策略保留原有的package-lock.json作为 Node.js 环境的基准运行bun install --lockfile生成bun.lockTOML 格式将bun.lock提交到 Git作为 Bun 环境的基准关键操作是bun add命令。它比npm install更智能bun add axios自动安装最新兼容版本并写入package.json的dependenciesbun add -d vitest安装到devDependenciesbun add lodash4.17.21精确指定版本不带^或~但我们遇到一个坑bun add会自动修改package.json的engines字段添加bun: 1.0.0。这导致 CI 系统在 Node.js 环境下执行npm install时因engines不匹配而失败。解决方案在 CI 脚本中添加sed -i /bun:/d package.json删除该字段或使用npm install --ignore-engines忽略引擎检查。4.3 第三步构建与测试——用bun build和bun test替代 Webpack/Jestbun build的配置极其简洁但正因如此容易忽略细节。我们的api-service项目原本用 Webpack 打包配置了externals: { express: commonjs express }避免把express打包进去。Bun 的bun build默认会把所有import的包都打包导致输出文件包含express代码体积暴涨 4.2MB。解决方案使用--target node和--external标志bun build --target node --external express --external pg index.ts --outdir dist--target node告诉 Bun 输出 CommonJS 模块而非默认的 ESM--external指定这些包不打包运行时动态require。bun test的坑在于jest.mock()的行为差异。Node.js 下jest.mock(fs)会替换整个fs模块Bun 下它只替换fs.promises的方法fs.readFileSync仍调用原生实现。解决方案改用vi.mock()Vitest 风格它是 Bun 测试运行器原生支持的vi.mock(fs, async () { const original await vi.importActual(fs); return { ...original, readFileSync: vi.fn().mockReturnValue(mocked content), }; });4.4 第四步生产部署——Docker 镜像与 CI/CD 流水线改造最大的挑战不是代码而是基础设施。我们的 CI/CD 使用 GitHub Actions原有流程是- name: Install Node.js uses: actions/setup-nodev3 with: node-version: 18 - name: Install dependencies run: npm ci - name: Run tests run: npm test迁移到 Bun 后必须重写- name: Install Bun uses: oven-sh/bun-setupv1 - name: Install dependencies run: bun install --frozen-lockfile - name: Run tests run: bun test关键点bun install --frozen-lockfile确保安装版本与bun.lock完全一致避免 CI 环境与本地不一致Dockerfile 也要改原来用node:18-alpine基础镜像现在用oven/bun:latest生产镜像体积从 327MBNode.js Alpine降到 189MBBun Alpine因为 Bun 的二进制包含所有工具链无需额外安装npm、yarn、tsc但有个严重问题oven/bun:latest镜像不支持 ARM64Apple Silicon。我们在 M2 Mac 上本地构建成功CIx86_64也成功但部署到 AWS GravitonARM64实例时失败。解决方案改用multiarch镜像或在 Dockerfile 中显式指定平台FROM --platformlinux/amd64 oven/bun:latest虽然牺牲了 ARM64 原生性能但保证了跨平台一致性。5. 未来三年演进预测Bun 会走向何方作为每天都在用 Bun 写代码、也持续关注 Node.js RFCRequest for Comments的开发者我不做“谁赢谁输”的赌局而是观察两者如何在各自轨道上进化。基于 Bun 的 GitHub Roadmap、Node.js 的官方会议纪要以及我们团队的实际使用反馈我对未来三年做出以下预测每一条都附带可验证的判断依据。5.1 Bun 的必然进化从“CLI 工具链”到“边缘计算运行时”Bun 的当前定位是“开发者工具链”但它的技术基因注定它会向“边缘计算”延伸。理由有三Zig 胶水层的极致轻量Bun 的二进制大小仅 32MB含所有工具而 Node.js npm typescript jest 的最小镜像超过 200MB。Cloudflare Workers、Vercel Edge Functions 等边缘平台对冷启动时间和内存占用极度敏感Bun 是天然适配者。内置 HTTP 服务器的潜力Bun.serve()API 已支持 WebSocket、HTTP/2、TLS但目前缺乏生产级特性如连接池、请求超时、负载均衡。预计 2025 年Bun 会推出bun serve --prod模式集成这些能力。**WebAssembly 的