首页 / Bun 入门教程 / 第一个 Bun 程序

Bun 入门教程

第一个 Bun 程序

本教程共 34 篇 · 第 3 篇 · 更新于 2026-08-06

Bunbun runREPLbun createTypeScript快速上手

本节目标:

  • bun run 直接执行一个 .ts / .tsx / .js 文件,体会「免编译」
  • 学会用 bun repl 做即时的表达式试验
  • bun createbun init 拉起一个可运行的最小项目骨架
  • 理解 Bun 项目里 index.tspackage.jsontsconfig.json 各自扮演的角色

安装好 Bun 之后,最直观的验证方式就是真的跑一段代码。Bun 的一大卖点正是「开箱即跑 TypeScript 和 JSX」,不需要你先配置 tscts-node、构建步骤或者任何 loader。这一节我们就从一行命令开始。

3.1 直接运行一个文件

新建一个文件,比如 hello.ts,内容只有一行:

console.log("Hello via Bun!");

然后在文件所在目录执行:

bun run hello.ts

终端会立刻打印出 Hello via Bun!。注意这里我们用的是 .ts 文件,里面写了 TypeScript 的类型语法也能照常跑。例如:

function greet(name: string): string {
  return `Hello, ${name}!`;
}

console.log(greet("Bun"));

bun run 会在加载阶段用内置的转译器把类型标注「剥离」掉,再把纯 JavaScript 交给 JavaScriptCore 执行。整个过程对用户是透明的,你不需要先 tsc 编译、也不需要额外的运行时插件。

Note

bun run <文件> 与直接 bun <文件> 效果相同,例如 bun hello.tsbun run 这个写法更常见于「运行 package.json 里的脚本」,二者可以混用。

除了 TypeScript,Bun 也能直接执行 .js.jsx.tsx.mjs.cjs.mts.cts 等常见扩展名。JSX / TSX 的转译同样内置,不需要 Babel 或 esbuild 预处理。

Bun 默认把文件当作 ES 模块(ESM)处理,这与 Node.js 的现代默认行为一致。写 CommonJS 风格的 require() 也能跑,同一个项目里 ESM 与 CJS 可以混用。

所以不管你是从老项目迁过来,还是直接写新语法,基本不用为模块格式操心。

Tip

想确认 Bun 成功加载了哪个文件、解析路径是什么,可以临时在代码里 console.log(import.meta.url) 打印当前模块地址,或用 console.log(__filename) / console.log(__dirname) 查看文件与目录路径(这两个是 Node.js 兼容全局,Bun 同样支持)。

3.2 运行 package.json 里的脚本

在真实项目里,命令通常写在 package.jsonscripts 字段中。bun run <脚本名> 会读取该字段并执行对应的命令。

{
  "name": "my-app",
  "module": "index.ts",
  "scripts": {
    "start": "bun run index.ts",
    "dev": "bun --hot index.ts"
  }
}
bun run start
# 等价于执行 scripts.start 里的 "bun run index.ts"

这与 npm run 的用法一致,但 bun run 启动一条脚本的固定开销小得多,官方基准里能差出一个数量级。原因是它省掉了 Node 进程与脚本包装那一层。

这只是启动开销的差异。业务代码本身跑多快,跟用哪个命令启动没有关系,别把这个倍数套到运行性能上。

Tip

如果只是想临时执行一小段代码,可以用 bun -ebun --eval

bun -e 'console.log(1 + 1)'

加上 -p / --print 还会把结果打印出来,适合做一次性计算。

3.3 用 REPL 做即时试验

不想建文件时,可以用交互式 REPL(Read-Eval-Print Loop)直接敲代码:

bun repl
Welcome to Bun v1.3.14
Type .copy [code] to copy to clipboard. .help for more info.

> 1 + 1

2
> const greeting = "Hello, Bun!"

undefined
> greeting

'Hello, Bun!'

REPL 的几个实用特性:

  • 原生支持 TypeScript 与 JSX:可以当场写带类型标注或 JSX 的表达式,Bun 会自动转译。
  • 顶层 await:不用包在 async 函数里就能 await 一个 Promise。
  • 语法高亮:输入时实时着色,长表达式更容易看出括号是否配对。
  • 历史记录持久化:保存在 ~/.bun_repl_history(最多 1000 条),跨会话可用 Up / Down 翻找。
  • Tab 补全:按 Tab 补全属性名或命令;未闭合的括号会自动换行续写。
  • Node.js 全局可用requiremodule__dirname__filename 都能用,且相对当前工作目录解析。

REPL 里还有两个特殊变量:

变量含义
_上一次表达式的结果
_error上一次抛出的错误
> 2 + 2

4
> _ * 10

40

常用命令以 . 开头:.help(帮助)、.exit(退出)、.clear(清屏)、.history(打印历史)、.load ./script.ts(载入文件)、.save ./session.txt(导出历史)、.editor(多行编辑模式,Ctrl+D 求值)、.copy <表达式>(复制结果到剪贴板)。

Tip

非交互场景可以用 bun repl -e / -p 以 REPL 语义求值后退出,比如 bun repl -p "await fetch('https://example.com').then(r => r.status)",适合写进脚本或 CI 里做连通性探测。

3.4 用 bun create 拉起项目骨架

想从零开始一个更完整的项目,可以用 bun create(或先 bun init)。两者定位不同:

  • bun init <目录>:生成一个空的 Bun 项目骨架,交互式选择模板(Blank / React / Library)。
  • bun create <模板>:从一个 React 组件、create-<模板> npm 包、GitHub 仓库或本地模板,生成完整项目。

最简单的空项目:

bun init my-app
cd my-app
bun run index.ts

bun init 会创建 package.jsontsconfig.jsonindex.tsREADME.md.gitignore 等文件,并在结束时自动执行 bun install 安装 @types/bun(Bun 的 TypeScript 类型声明)。如果一路回车接受默认值,等价于加 -y / --yes

bun init -y my-app
Note

bun init 是「非破坏性」的:多次运行不会覆盖你已有的文件,可以放心在已有目录里补生成配置。

如果你手头有一个 React 组件文件 MyComponent.tsxbun create 还能把它变成一个带热重载的开发环境:

bun create ./MyComponent.tsx

Bun 会分析组件的模块图、收集依赖、生成 .html 与入口文件,并启动前端开发服务器。它也支持 TailwindCSS 与 shadcn/ui 的自动探测配置,但这些属于进阶用法,初学阶段了解即可。

3.5 从 GitHub 或 npm 模板起步

bun create 还能直接拉取远程模板:

# 从 npm 上的 create-<模板> 包
bun create remix

# 从 GitHub 仓库
bun create user/repo
bun create github.com/user/repo mydir

远程模板默认不会覆盖已有文件;如需覆盖加 --force。Bun 会下载模板、复制文件、执行 bun install、并初始化一个全新的 Git 仓库(可用 --no-git 跳过,--no-install 跳过安装)。

Warning

本地模板的行为与远程不同:用 bun create <本地名> 时,如果目标目录已存在,Bun 会直接删除整个目标目录再写入。本地模板放在 $HOME/.bun-create/<名>(全局)或 <项目>/.bun-create/<名>(项目级)。请务必注意目标目录里是否有重要文件。

3.6 项目里的三个关键文件

bun init 生成的项目,最重要的三个文件是:

index.ts —— 入口文件。Bun 默认按优先级寻找入口:package.jsonmodule / main 字段,或存在的 index.{tsx,ts,jsx,js,mts,mjs}

package.json —— 项目的元数据与脚本入口。Bun 会读取其中的 scriptsdependencies 等字段。一个最小示例:

{
  "name": "my-app",
  "module": "index.ts",
  "type": "module",
  "private": true,
  "scripts": {
    "start": "bun run index.ts"
  },
  "devDependencies": {
    "@types/bun": "latest"
  }
}

tsconfig.json —— 主要给编辑器提供类型提示与自动补全(比如 Bun 全局对象的类型)。Bun 运行时本身不依赖它来做转译,但会读取其中的 paths(路径别名)和 jsx 相关配置。建议的 compilerOptions 包含:

{
  "compilerOptions": {
    "lib": ["ESNext"],
    "target": "ESNext",
    "module": "Preserve",
    "moduleDetection": "force",
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "jsx": "react-jsx",
    "types": ["bun"]
  }
}
Warning

Bun 运行 TypeScript 只做转译、不做类型检查。也就是说,即使你的代码里有类型错误,只要能转译成合法 JavaScript,Bun 依然会跑。类型检查请交给编辑器或单独的 tsc --noEmit 步骤。这是「免编译秒跑」的代价,也是设计取舍,并非 bug。

3.7 一个最小可运行示例

index.ts 换成下面这段,体验一下 Bun 内置的 HTTP 能力(无需安装任何框架):

const server = Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response("Hello from Bun!");
  },
});

console.log(`Listening on ${server.url}`);
bun run index.ts
# 打开 http://localhost:3000 即可看到 "Hello from Bun!"

Bun.serve 是 Bun 自带的 HTTP 服务器 API(属于 Bun.* 原生 API)。这里先跑通即可,后面的章节会专门讲热重载与全栈开发服务器。

3.8 小结与常见误区

  • bun run 文件bun 文件 都能直接执行 TypeScript / JSX,无需预编译。
  • bun repl 适合做快速试验,支持 TS、顶层 await、历史持久化。
  • bun init 生成空骨架,bun create 从模板生成完整项目;二者都可选。
  • tsconfig.json 主要服务于编辑器,运行时转译不依赖它;但 pathsjsx 配置 Bun 会读取。
  • Bun 转译 TypeScript 不做类型检查,类型错误不会阻止运行。
Note

如果编辑器里 Bun 全局对象报类型错误,先确认已安装 @types/bunbun add -d @types/bun),且 tsconfig.jsoncompilerOptions.types"bun"。这不影响运行,只是编辑器提示问题。