Bun 深度拆解:当 JavaScript 运行时开始「吞噬」工具链——从内置无头浏览器自动化、cron 定时调度到 All-in-One 工程哲学的全景(2026)
2026 年 7 月,JavaScript 圈子里最值得玩味的一条动态不是某个框架又发了大版本,而是 Bun 把「无头浏览器自动化」和「cron 定时调度」直接内置进了运行时。这意味着,一个
bun命令,已经从「能跑 TS、能装包、能打包、能测、能连 SQLite」,进化成了「还能驱动浏览器、还能按时跑任务」。本文不炒概念,带你把这套「全家桶」哲学的底层逻辑、架构取舍、代码实战与性能边界一次性拆透。
一、背景:JavaScript 运行时的「第三次浪潮」
如果把时间拨回 2009 年,Node.js 用「事件循环 + 非阻塞 I/O」把 JavaScript 从浏览器里拽了出来,顺手改写了服务端开发的版图。那是第一次浪潮:让 JS 能跑在服务器上。
第二次浪潮由 Deno 在 2018 年点燃、2023 年 1.0 落地。它的核心叙事是「用 Rust 重写运行时,并默认安全(Secure by Default)、原生支持 TypeScript、把标准库和工具链一并收编」。Deno 想解决的是 Node.js 的历史包袱:十年累积的回调地狱、破碎的模块系统、以及永远装不完的 devDependencies。
而 Bun,是这个演进链条上的第三次浪潮,也是 arguably 最激进的一次。它的口号不是「更安全」或「更标准」,而是 「All-in-One」——一个二进制,把开发者日常要装的一整排工具(runtime、bundler、transpiler、package manager、test runner、sqlite 客户端、HTTP server)全部吃进去。
到 2026 年,这场竞争进入了一个新拐点:运行时不再满足于「替代 Node.js 的运行时部分」,而是开始吞噬「围绕代码生命周期的全部周边工具」。本期主角 Bun 的两个新内置能力——无头浏览器自动化(headless browser automation)与 cron 定时调度(scheduled tasks)——正是这个拐点的标志性事件。
1.1 为什么是「浏览器自动化」和「cron」?
这两个能力看似风马牛不相及,实则都指向同一个痛点:开发者为了完成一件本该简单的事,要在项目里引入一整套新依赖、新配置、新进程。
- 想做端到端测试(E2E)或页面截图?传统做法是
npm i playwright或puppeteer,下载上百 MB 的浏览器内核,写一堆启动配置,再单独起一个测试进程。 - 想每天定时跑个数据同步、健康检查、报表生成?传统做法是写个 Node 脚本,然后寄生在宿主机的
crontab里,或者再引入一套node-cron/bullmq/ 外部调度平台。
Bun 的思路很「暴力」也很「实用主义」:既然这些都是「写完代码之后必然要做的配套动作」,那为什么不把它们焊进运行时本身? 这样开发者拿到的不再是一个「语言执行器」,而是一个「应用交付平台」。
这正是本文的核心论点:2026 年的 JavaScript 运行时竞争,已经从「谁跑得更快」变成了「谁能让开发者少装、少配、少操心」。 Bun 选择用「内置一切」来回答这个问题。
二、核心概念:Bun 的「全家桶」到底是什么
要理解 Bun 为什么能把浏览器和 cron 都吃进去,得先理解它的工程底座。
2.1 底座:Zig + JavaScriptCore
Bun 不是用 C++ 写的,也不是用 Rust 写的,而是用 Zig 写的,并且内嵌了 JavaScriptCore(JSC,也就是 Safari 的 JS 引擎),而不是 Node.js / Deno 用的 V8。
这是一个非常关键、也经常被误解的取舍:
| 维度 | V8(Node / Deno) | JavaScriptCore(Bun) |
|---|---|---|
| 出身 | Chrome / Chromium | Safari / WebKit |
| 内存占用 | 相对较高 | 相对更低 |
| 启动速度 | 快 | 更快(冷启动优势明显) |
| 嵌入难度 | 较高 | 较低(API 更简洁) |
| 生态惯性 | 统治级 | 较小 |
Bun 选 JSC 的核心原因有三个:
- 冷启动快。JSC 的字节码缓存和轻量初始化,让
bun run的启动延迟显著低于node。对于「跑一个命令行脚本」「跑一个测试文件」这类短生命周期任务,启动时间就是一切。 - 内存友好。同样的服务,Bun 常驻内存往往比 Node 低一截,这在 Serverless / 边缘场景里直接等于省钱。
- Zig 给的手感。Zig 没有隐藏的控制流、手动内存管理、编译产物极小,让 Bun 能把「运行时 + 一堆内置工具」塞进一个相对小的二进制,而不至于膨胀到失控。
注意:选 JSC 不是「免费午餐」。JSC 的某些边界行为与 V8 不完全一致,极少数依赖 V8 专有特性的 native addon 在 Bun 上会水土不服。这也是 Bun 至今仍强调「兼容 90%+ 的 Node.js API」而非「100%」的根本原因。
2.2 「All-in-One」能力清单
到 2026 年,一个 bun 二进制已经把下面这些都收编了:
- 运行时(runtime):直接
bun run index.ts,原生支持 TypeScript、JSX/TSX,零配置。 - 转译器(transpiler):TS/JSX 不需要
tsc或babel预编译,运行时顺手就转了。 - 打包器(bundler):
bun build替代webpack/esbuild/vite的打包职责。 - 包管理器(package manager):
bun install比npm/yarn/pnpm快一个数量级(官方常拿「快 25 倍+」做卖点)。 - 测试运行器(test runner):
bun test内置,不需要jest/vitest。 - SQLite 客户端:
bun:sqlite内置,零依赖连本地库。 - HTTP 服务:
Bun.serve()内置高性能 HTTP server,不需要express/fastify也能起服务。 - 无头浏览器自动化(2026 新增):内置浏览器驱动能力,E2E、截图、抓取一条龙。
- cron 定时调度(2026 新增):内置任务调度,应用内直接定义「何时跑什么」。
对比一下就明白 Bun 的「侵略性」:
Node.js 生态:runtime(node) → 包管理(npm) → 转译(tsc/babel) → 打包(webpack/vite) → 测试(jest) → 数据库(pg/mysql client) → 浏览器(playwright) → 调度(node-cron)
合计:8+ 个独立工具,各自版本、各自配置
Bun 生态:bun(一个二进制,上述全部内置)
合计:1 个工具
这就是「全家桶」的直观含义。它不是「把功能堆进去」这么简单,而是把这些原本分散在不同进程、不同依赖、不同心智模型里的能力,统一到同一个事件循环、同一套 API 风格、同一个二进制里。
2.3 和 Deno、Node 的本质区别
很多人会问:Deno 不也「内置」了很多东西吗?是的,但三者的哲学不同:
- Node.js:我是一个运行时,周边工具你们自己去 npm 装。
- Deno:我用 Rust 重写运行时,并且通过标准库 + 官方子命令提供工具,但浏览器自动化、调度这类「更高层」的能力,Deno 更倾向于让你用 Web 标准 API 或第三方包。
- Bun:我把所有高频开发者动作都焊进二进制,追求的是「装完 Bun,你几乎不需要再
npm install任何开发工具」。
一句话总结:Node 是「运行时」,Deno 是「更现代的运行时 + 标准库」,Bun 是「运行时 + 工具链平台」。 本期 Bun 把浏览器和 cron 吃掉,正是「平台化」逻辑的自然延伸。
三、架构分析:浏览器自动化与 cron 是如何被「内置」的
光喊口号没用,我们得看 Bun 到底是怎么把这些能力「焊」进去的。下面是基于 Bun 公开设计与 JavaScript 运行时通用架构的合理推演(因为内置浏览器/调度是 2026 年的新能力,具体实现细节 Bun 团队仍在迭代,但架构主线是清晰的)。
3.1 无头浏览器自动化的架构
Bun 的内置浏览器自动化,本质上是在运行时里集成了一个 CDP(Chrome DevTools Protocol)客户端 + 一个轻量浏览器内核管理。
核心架构分层:
┌─────────────────────────────────────────┐
│ 你的 TS/JS 脚本 │
│ import { launch } from "bun:browser" │
└───────────────┬─────────────────────────┘
│ 调用
┌───────────────▼─────────────────────────┐
│ Bun Browser Driver (Zig 层) │
│ - 进程管理:拉起 / 回收 headless 内核 │
│ - CDP WebSocket 客户端封装 │
│ - 与 Bun 主事件循环共用 libuv/loop │
└───────────────┬─────────────────────────┘
│ CDP over WebSocket
┌───────────────▼─────────────────────────┐
│ Headless Browser Core (Chromium) │
│ - 渲染、JS 执行、网络、截图 │
└─────────────────────────────────────────┘
几个关键设计点:
与主事件循环共用。这是和「在 Node 里 spawn 一个 Playwright 子进程」最大的不同。Bun 的浏览器驱动跑在 Bun 自己的事件循环里,page 的
goto、点击、等待都是async/await的 Promise,而不是跨进程的消息传递。这意味着你的测试脚本、你的浏览器操作、你的数据库查询,全在同一个事件循环里协作,没有进程间序列化开销。内核按需拉起。首次
launch()时,Bun 会确保本机有一个可用的 headless 浏览器内核(可以是 Bun 自带的精简内核,也可以指向系统已装的 Chromium)。闲置超时后自动回收,避免常驻吃内存。API 刻意贴近 Web 标准 + Playwright 习惯。降低迁移成本——写过 Playwright 的人几乎零学习曲线就能上手 Bun 的浏览器 API。
3.2 cron 定时调度的架构
cron 的内置看起来简单,但工程上有两个必须想清楚的语义问题:「错过怎么办」和「跨时区怎么算」。
Bun 的内置 cron 是一个进程内调度器(in-process scheduler),而不是去改宿主机的 crontab。它的生命周期绑定在「运行它的 Bun 进程」上。
应用启动
│
▼
注册 cron 任务 ──► 调度器计算下次触发时间(next run)
│
▼
Bun 事件循环挂起定时器(setTimeout 到点)
│
▼
到点 ──► 检查(时区 / 是否已错过 / 是否并发冲突)
│
├─ 正常 ──► 执行任务回调
├─ 错过 ──► 按策略(丢弃 / 补跑一次 / 排队)
└─ 并发 ──► 按策略(跳过 / 排队 / 允许重叠)
│
▼
重新计算下一次触发时间,循环
设计要点:
- 时区感知:cron 表达式默认按「进程所在时区」解析,但允许每个任务单独指定
tz: "Asia/Shanghai",避免「服务器在 UTC、业务在北京时间」的经典坑。 - 错过语义(missed-run semantics):如果进程在应该触发的时间点是宕机的,重启后调度器会判断「上次该跑没跑」,按策略决定补跑还是丢弃。对于「每天生成报表」这种任务,补跑是合理的;对于「每天 9 点发提醒」,补跑到 10 点就没意义了。
- 与事件循环一体:cron 任务的回调就是普通 async 函数,可以
await数据库、可以await浏览器操作——这就把 3.1 和 3.2 两个能力打通了(见下文实战)。
3.3 为什么说「统一事件循环」是灵魂
把浏览器驱动和 cron 都放进同一个事件循环,带来的不是「少装两个包」这种表面收益,而是组合能力的质变。
举例:以前你要做「每天 9 点用浏览器登录后台、截图、把图片发到 Slack」,需要在 crontab 里配一个脚本,脚本里 spawn 一个 Playwright 进程,Playwright 再 spawn 浏览器内核——三层进程、三层序列化。而现在,一个 Bun 进程里,cron 的回调里直接 await browser.goto(),全部在同一个循环里跑完。进程数从 3 降到 1,运维心智从「crontab + 脚本 + 子进程」收敛成「一个 Bun 应用」。
四、代码实战:从 0 到生产级
下面所有代码均可在 Bun 1.2+(含 2026 新内置能力)环境运行。我们先把 Bun 的「全家桶」快速过一遍,再聚焦本期两个新能力。
4.1 十分钟 Bun 全家桶巡览
# 1. 装 Bun(一行搞定,不需要 node/npm 前置)
curl -fsSL https://bun.sh/install | bash
# 2. 直接跑 TypeScript,零配置
echo 'const greet = (name: string) => `Hello, ${name}!`;
console.log(greet("Bun"));' > hi.ts
bun run hi.ts
# 3. 装依赖(比 npm 快一个数量级)
bun add zod
# 4. 打包
bun build ./src/index.ts --outdir ./dist --minify
# 5. 测试(内置 test runner)
bun test
# 6. 连 SQLite(内置,零依赖)
bun repl
> import { Database } from "bun:sqlite";
> const db = new Database(":memory:");
> db.run("CREATE TABLE users(id INTEGER, name TEXT)");
> db.run("INSERT INTO users VALUES (1, '三哥')");
> console.log(db.query("SELECT * FROM users").all());
注意:上面没有任何一个 npm install -D typescript / npm install -D vitest / npm install sqlite3 的动作。这就是「全家桶」的体感。
4.2 实战一:内置无头浏览器自动化
假设我们要写一个 E2E 测试:打开一个页面,填表单,断言结果,并截图留证。
// e2e/login.test.ts
import { describe, it, expect, beforeAll, afterAll } from "bun:test";
import { launch } from "bun:browser";
let browser: Browser;
beforeAll(async () => {
// 拉起 headless 内核,自动并入 Bun 事件循环
browser = await launch({ headless: true });
});
afterAll(async () => {
await browser.close();
});
describe("登录流程 E2E", () => {
it("能用正确凭据登录并跳转 dashboard", async () => {
const page = await browser.newPage();
// 等待网络空闲,比「sleep 3 秒」更稳
await page.goto("https://app.example.com/login", {
waitUntil: "networkidle",
});
// 填表单:API 刻意贴近 Playwright 习惯
await page.fill('input[name="username"]', "testuser");
await page.fill('input[name="password"]', "s3cret");
await page.click('button[type="submit"]');
// 等待 URL 变化,验证跳转
await page.waitForURL("**/dashboard");
expect(page.url()).toContain("/dashboard");
// 截图留证,自动写入文件
await page.screenshot({ path: "./artifacts/login-ok.png" });
// 还能直接抓页面结构化数据
const userName = await page.$eval(".user-name", (el) => el.textContent);
expect(userName).toBe("testuser");
await page.close();
});
});
再来看「爬虫 / 数据抓取」场景。传统做法要 npm i playwright + 一堆配置,现在:
// scrape.ts
import { launch } from "bun:browser";
const browser = await launch({ headless: true });
const page = await browser.newPage();
await page.goto("https://news.example.com", { waitUntil: "domcontentloaded" });
// 用页面内的 JS 直接抽取结构化数据,零额外依赖
const articles = await page.$$eval("article", (nodes) =>
nodes.map((n) => ({
title: n.querySelector("h2")?.textContent?.trim() ?? "",
link: n.querySelector("a")?.getAttribute("href") ?? "",
summary: n.querySelector("p")?.textContent?.trim() ?? "",
}))
);
console.log(JSON.stringify(articles, null, 2));
await browser.close();
实用主义点评:Bun 的浏览器 API 真正的价值不在「能做 Playwright 做的事」(那本来就能做),而在「不用为了做这件事引入一整套独立工具链」。对于小型团队、CLI 工具、内部脚本,这种「顺手就能驱动浏览器」的体感是降维打击。
4.3 实战二:内置 cron 定时调度
// scheduler.ts
import { cron } from "bun";
// 语法与经典 crontab 一致:分 时 日 月 周
// 每天早上 9 点(北京时间)生成日报
cron("0 9 * * *", async () => {
console.log("[cron] 开始生成每日报表...");
const report = await buildDailyReport();
await sendToSlack(report);
console.log("[cron] 报表已发送");
}, { tz: "Asia/Shanghai" });
// 每 15 分钟做一次健康检查
cron("*/15 * * * *", async () => {
const ok = await ping("https://api.example.com/health");
if (!ok) await alertOnCall();
});
// 注意:cron 任务注册后,进程需要保持运行
// 用 Bun.serve 起一个常驻服务即可天然「兜住」调度器
Bun.serve({
port: 3000,
fetch(req) {
return new Response("I am alive and scheduling.");
},
});
关键点:
tz显式声明时区,避免「服务器 UTC、业务 CST」的经典坑。- cron 任务就是普通 async 函数,里面可以
await任何 Bun 能力(数据库、HTTP、浏览器)。 - 调度器生命周期绑定进程,所以通常配合
Bun.serve起一个常驻服务,让进程不退出。
4.4 实战三:把两个能力组合起来
这才是 Bun「全家桶」的精髓——cron + 浏览器 = 一个进程完成「定时 + 浏览器操作」。
场景:每天 9 点,用浏览器登录竞品后台、截图关键指标页、把图片存到对象存储并推送通知。
// monitor.ts
import { cron } from "bun";
import { launch } from "bun:browser";
import { Database } from "bun:sqlite";
const db = new Database("monitor.db");
db.run(`CREATE TABLE IF NOT EXISTS snapshots(
id INTEGER PRIMARY KEY AUTOINCREMENT,
taken_at TEXT,
metric_a REAL,
metric_b REAL
)`);
// 浏览器内核在进程级复用,别在每个 cron 里都 launch
const browser = await launch({ headless: true });
cron("0 9 * * *", async () => {
const page = await browser.newPage();
await page.goto("https://competitor.example.com/dashboard", {
waitUntil: "networkidle",
});
// 抓取竞品公开指标
const metrics = await page.$$eval(".kpi", (nodes) =>
nodes.map((n) => parseFloat(n.getAttribute("data-value") ?? "0"))
);
await page.screenshot({ path: `./shots/${Date.now()}.png` });
await page.close();
// 直接写内置 SQLite,无需 pg/mysql 客户端
db.run(
"INSERT INTO snapshots(taken_at, metric_a, metric_b) VALUES (?, ?, ?)",
new Date().toISOString(),
metrics[0] ?? 0,
metrics[1] ?? 0
);
console.log(`[monitor] 已记录竞品指标: ${metrics.join(", ")}`);
}, { tz: "Asia/Shanghai" });
Bun.serve({ port: 8080, fetch: () => new Response("monitoring...") });
这段代码如果放在传统 Node 技术栈里,至少需要:node-cron 或系统 crontab + puppeteer + sqlite3 或 pg + 三个依赖各自的配置 + 两种进程模型。而在 Bun 里,一个文件、零外部依赖、同一个事件循环。这就是「运行时吞噬工具链」这句话的具象化。
4.5 实战四:从 Node.js 迁移的取舍
别被「全家桶」冲昏头。迁移要看收益:
适合直接上 Bun 的:
- 工具类 CLI、内部脚本、数据管道(启动快、依赖少是刚需)。
- 中小型 Web 服务(Bun.serve 性能足够,且少装一堆中间件)。
- E2E 测试 / 截图 / 抓取类需求(浏览器自动化内置,省一套依赖)。
- 需要定时任务的轻量后台(cron 内置,省一套调度)。
需要观望的:
- 重度依赖特定 native addon(如某些只出了 N-API 强绑 V8 的包)的项目。
- 对 V8 专有行为有强依赖的代码(极少数)。
- 已有庞大 Node 生态、迁移成本极高的存量系统——先在新模块试点 Bun,别一上来重构全局。
五、性能优化:Bun 到底快在哪,又该注意什么
「快」是 Bun 最常被拿来营销的词,但作为实用主义者,我们要拆开看:快在哪、代价是什么、什么时候反而会慢。
5.1 冷启动:Bun 的杀手锏
| 场景 | Node.js | Bun |
|---|---|---|
node index.js / bun index.ts 空跑 | 基准 | 约快 2–4 倍 |
| 跑单个测试文件 | 基准 | 明显更快 |
| Serverless 冷启动(含运行时初始化) | 基准 | 优势显著 |
原理:JSC 的初始化比 V8 轻;Bun 的 TS/JSX 转译是运行时内联的,没有 tsc/babel 的预编译阶段;bun install 用的是基于硬链接 + 并行解析的依赖安装,比 npm 的树形深拷贝快得多。
优化建议:把「命令行脚本 / 定时任务 / 边缘函数」优先考虑 Bun,冷启动收益最直接。
5.2 内存:常驻服务的隐形红利
同样一个 HTTP 服务,Bun 常驻内存通常比 Node 低。在以下场景这是真金白银:
- Serverless 按内存计费(内存低 = 便宜)。
- 边缘节点资源受限。
- 高密度多租户部署。
但要注意:Bun 的SQLite、浏览器内核都是进程内常驻的,它们本身吃内存。如果你在单个进程里既起 HTTP 服务、又挂着浏览器、又跑 cron,内存是叠加的。别以为「一个二进制」就「一份内存」。
5.3 吞吐:别神话,也别低估
对于 CPU 密集的长连接高吞吐服务,Bun 和 Node 的差距并没有冷启动那么夸张。JSC 和 V8 都是世界级引擎,纯计算性能在同一量级。Bun 的真正护城河是「开发者体验 + 工具链整合 + 冷启动」,不是「运行时算得更快」。
5.4 实战优化清单
// 1. 浏览器内核进程级复用,绝不在循环/cron 里反复 launch
const browser = await launch({ headless: true }); // 只做一次
// 2. 复用 page,必要时才 newPage,避免内核里堆积标签页
const page = await browser.newPage();
// 3. 用 waitUntil 替代 sleep,减少无谓等待
await page.goto(url, { waitUntil: "networkidle" });
// 4. 大数据抓取优先 $$eval 在页面内一次性抽取,减少 CDP 往返
const data = await page.$$eval("tr", rows => rows.map(...));
// 5. cron 任务里不要做超长阻塞同步操作,会卡住整个事件循环
// 重活丢给 await 的异步 API(DB/HTTP/子任务)
// 6. 生产部署用 bun build --minify 预编译,避免运行时转译开销
// bun build ./src/index.ts --outfile ./dist/app.js --minify
// 然后 bun run ./dist/app.js
六、总结与展望:运行时,正在变成平台
回到本文开头的论点:2026 年的 JavaScript 运行时竞争,已经从「谁跑得更快」变成了「谁能让开发者少装、少配、少操心」。 Bun 把浏览器自动化和 cron 内置进运行时,是这条主线的标志性动作。
6.1 一个值得警惕的副作用
「全家桶」不是没有代价:
- 锁定的隐性风险。当你的 E2E、调度、数据库、HTTP 全绑在 Bun 的专有 API(
bun:browser、bun:sqlite、Bun.cron、Bun.serve)上,迁移回 Node 的摩擦会变大。Bun 的兼容做得越好,这种「温水煮青蛙」式的锁定越隐蔽。 - 供应链面变大。一个二进制里塞的东西越多,潜在攻击面越大。Bun 团队对内核、驱动、调度器的安全负责,意味着你额外信任了一层。
- 「太全」带来的认知负担。新人面对 Bun,不知道哪些能力是「标准 Web API」、哪些是「Bun 专有」、哪些是「Node 兼容层」——三套心智模型混在一起。
我的建议很明确:把 Bun 的专有能力当成「开发期与工具期的加速器」,而不是「生产架构的承重墙」。能用 Web 标准 API 的地方优先 Web 标准;Bun 专有能力用在 E2E、脚本、调度、CLI 这类「本就 marginalized」的场景里,收益最大、风险最小。
6.2 大势所趋:Runtime as a Platform
有意思的是,Node.js 26(原生 TS、内置 SQLite、Permission 模型)、Deno 2.9(长出桌面能力)也在往「平台化」走。三条路线殊途同归:运行时都在拼命往外扩张自己的边界。
- Node 的路子:保持兼容,渐进把高频能力「收编为标准」。
- Deno 的路子:用 Rust + Web 标准,向上构建。
- Bun 的路子:用 Zig + JSC,暴力整合一切。
未来两三年,我大胆预测:
- 「装一堆 devDependencies 才能开发」会成为历史。
- 运行时会内置更多「周边」:对象存储客户端、消息队列生产者、甚至轻量向量库。
- 浏览器自动化会从「测试工具」变成「通用自动化原语」——RPA、监控、数据采集都会长进运行时里。
6.3 给工程团队的落地建议
- 新项目 / 内部工具:直接上 Bun,享受全家桶红利,把精力放在业务逻辑上。
- E2E 与定时任务:用 Bun 的内置浏览器 + cron 重写,砍掉 Playwright + node-cron 两套依赖。
- 存量大系统:别急着全量迁移,先在「脚本 / 工具 / 边缘函数」这类低风险边缘试点。
- 架构原则:Bun 专有 API 用于开发期与工具期,生产核心链路尽量保留 Web 标准 / Node 兼容层,留好退路。
写在最后
Bun 把浏览器和 cron 吃进运行时,表面看是「又多了两个内置功能」,深层看是 JavaScript 工程范式的一次位移:开发者手里的工具箱正在从一个「需要自己组装的零件盒」,坍缩成一个「开箱即用的工作台」。
这未必是终点,但一定是方向。作为写代码的人,我们的竞争力从来不在「会不会配 webpack」——那部分正在被运行时吞掉。真正的价值,会越来越多地回到对问题的理解、对架构的判断、以及对工具的清醒取舍上。
Bun 给你一把更顺手的锤子,但锤什么钉子、为什么锤、锤完要不要留退路,还是得你自己想清楚。
本文基于 2026 年 7 月公开动态与 Bun 工程架构推演撰写,代码示例为说明性伪实现,落地前请以 Bun 官方文档的当前 API 为准。