Skip to content

Bun

Bun 是另一款 JavaScript 运行时,它不是 Node.js,也不是 Deno。Bun 内置转译器,可以直接编写 TypeScript 代码,Hono 也能运行在 Bun 上。

1. 安装 Bun

请根据官方网站中的说明安装 bun 命令。

2. 环境准备

2.1 创建新项目

Bun 提供了对应的启动模板,可以通过 bun create 命令初始化项目。本示例选择 bun 模板。

sh
bun create hono@latest my-app

进入 my-app 并安装依赖:

sh
cd my-app
bun install

2.2 在现有项目中配置

如果你已经有 Bun 项目,只需在项目根目录安装 hono 依赖即可:

sh
bun add hono

3. Hello World

下面是 “Hello World” 示例,与其他平台基本相同。

ts
import { Hono } from 'hono'

const app = new Hono()
app.get('/', (c) => c.text('Hello Bun!'))

export default app

4. 运行

执行以下命令:

sh
bun run dev

然后在浏览器访问 http://localhost:3000

修改端口

可以通过导出 port 字段指定端口号。

ts
import { Hono } from 'hono'

const app = new Hono()
app.get('/', (c) => c.text('Hello Bun!'))

export default app 
export default { 
  port: 3000, 
  fetch: app.fetch, 
} 

提供静态文件

要提供静态文件,可从 hono/bun 引入 serveStatic

ts
import { serveStatic } from 'hono/bun'

const app = new Hono()

app.use('/static/*', serveStatic({ root: './' }))
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))
app.get('/', (c) => c.text('You can access: /static/hello.txt'))
app.get('*', serveStatic({ path: './static/fallback.txt' }))

上述代码可搭配以下目录结构正常运行:

./
├── favicon.ico
├── src
└── static
    ├── demo
    │   └── index.html
    ├── fallback.txt
    ├── hello.txt
    └── images
        └── dinotocat.png

rewriteRequestPath

如果需要将 http://localhost:3000/static/* 映射到 ./statics,可以使用 rewriteRequestPath 选项:

ts
app.get(
  '/static/*',
  serveStatic({
    root: './',
    rewriteRequestPath: (path) =>
      path.replace(/^\/static/, '/statics'),
  })
)

mimes

通过 mimes 可以补充额外的 MIME 类型:

ts
app.get(
  '/static/*',
  serveStatic({
    mimes: {
      m3u8: 'application/vnd.apple.mpegurl',
      ts: 'video/mp2t',
    },
  })
)

onFound

使用 onFound 可以在文件命中时执行额外逻辑:

ts
app.get(
  '/static/*',
  serveStatic({
    // ...
    onFound: (_path, c) => {
      c.header('Cache-Control', `public, immutable, max-age=31536000`)
    },
  })
)

onNotFound

使用 onNotFound 可在文件未找到时自定义处理:

ts
app.get(
  '/static/*',
  serveStatic({
    onNotFound: (path, c) => {
      console.log(`${path} is not found, you access ${c.req.path}`)
    },
  })
)

precompressed

启用 precompressed 后,会检测 .br.gz 等预压缩文件,并根据 Accept-Encoding 首选 Brotli,其次是 Zstd 和 Gzip;若都不存在,则返回原文件。

ts
app.get(
  '/static/*',
  serveStatic({
    precompressed: true,
  })
)

测试

在 Bun 中可以使用 bun:test 编写测试。

ts
import { describe, expect, it } from 'bun:test'
import app from '.'

describe('My first test', () => {
  it('Should return 200 Response', async () => {
    const req = new Request('http://localhost/')
    const res = await app.fetch(req)
    expect(res.status).toBe(200)
  })
})

然后执行:

sh
bun test index.test.ts

Released under the MIT License.