Chapter 03

bun run:脚本执行

比 npm run 快 150 倍启动,能直接跑 TypeScript/JSX,还内置热重载 —— 把它当你的"更好 node"。

3.1 三种命令行入口

$ bun foo.ts              # ① 直接运行文件
$ bun run foo.ts          # ② 同上,显式版本
$ bun run dev             # ③ 运行 package.json 里叫 dev 的脚本

规则:

3.2 package.json scripts

{
  "scripts": {
    "dev":    "bun --hot src/index.ts",
    "build":  "bun build src/index.ts --outdir dist",
    "test":   "bun test",
    "lint":   "bunx eslint .",
    "prestart": "bun run build",
    "start":  "bun dist/index.js"
  }
}
$ bun run dev
$ bun dev                 # 简写等价
$ bun test                # 内置命令(如 test/install)优先于脚本
bun run 比 npm run 快 150 倍

npm 启动时要加载大量 Node 模块(几百毫秒),而 Bun 是 Zig 原生启动——bun run dev 只需 4-6ms。这在频繁切脚本的 monorepo 里非常明显。

3.3 pre/post 钩子

兼容 npm 的 pre/post 钩子:

{
  "scripts": {
    "prestart": "bun run build",
    "start":    "bun dist/app.js",
    "poststart": "echo done"
  }
}

bun run start 自动跑 prestart → start → poststart。

3.4 --hot:热重载(开发用)

$ bun --hot src/server.ts

文件变更时 原地重载——保留 globalThis、HTTP 连接、WebSocket、定时器。特别适合开发 HTTP 服务器:状态不丢、客户端不断。

--watch:常规文件监听

$ bun --watch src/server.ts

文件变更时重启进程——所有状态重置。行为和 nodemon 一样。

--hot--watch
重载策略原地(保状态)重启进程
HTTP 连接保留断开
定时器 / setInterval保留清除
典型用法HTTP/WS 服务器一次性脚本 / CLI

3.5 环境变量

Bun 自动加载项目根的 .env 文件到 process.env

# .env
DATABASE_URL=postgres://localhost/db
PORT=3000
// src/server.ts
const port = Number(process.env.PORT) || 3000;

文件加载优先级(靠后覆盖靠前):

  1. .env
  2. .env.production / .env.development(按 NODE_ENV)
  3. .env.local
  4. .env.production.local

内联环境变量

$ NODE_ENV=production bun run src/server.ts
$ bun run --env-file=.env.staging src/server.ts

3.6 shebang:脚本直接可执行

脚本顶部加 shebang,chmod +x,就能当 CLI 用:

#!/usr/bin/env bun
// my-cli.ts
console.log("hi", process.argv.slice(2));
$ chmod +x my-cli.ts
$ ./my-cli.ts foo bar
hi [ "foo", "bar" ]

3.7 bunx:一次性运行(npx 替代)

$ bunx create-vite my-app        # 直接跑 npm 包的可执行
$ bunx cowsay 'hello'             # 临时用一次的 CLI
$ bunx --bun vite                # 强制用 bun runtime 跑 vite

--bun 参数让那些原本用 #!/usr/bin/env node 的 CLI 改用 bun 解释执行——某些情况下能提速 3 倍。

3.8 stdin / stdout 脚本流

$ echo 'console.log("hello")' | bun -
hello

$ bun -e 'console.log(Bun.version)'

-e(eval)传字符串、- 从 stdin 读——方便写 one-liner。

3.9 并发跑脚本:&

Bun 的 shell 内置(bun run 跑 scripts 时用的)支持 POSIX 语法:

{
  "scripts": {
    "dev": "bun run server & bun run web",
    "check": "bun run lint && bun run typecheck"
  }
}

或用 concurrently/npm-run-all,和 npm 生态兼容。

3.10 Bun Shell:$ 模板字符串

Bun 自带一个 JS 风格的 shell,用 $ 标签写命令:

import { $ } from "bun";

const files = await $`ls -1 src/`.text();
const branch = (await $`git rev-parse --abbrev-ref HEAD`.text()).trim();

// 管道与重定向
await $`cat package.json | jq .name > name.txt`;

// 传参时自动转义
const file = "my file.txt";
await $`ls ${file}`;    // 自动加引号,不会被分词

跨平台可用(Windows 也工作)、比 child_process.exec 安全(自动转义)、比 zx 轻量(零依赖)。

3.11 小结