Bun
Bun は、もう一つのJavaScriptランタイムです。Node.jsでもDenoでもありません。Bunにはトランスコンパイラが含まれており、TypeScriptでコードを書くことができます。HonoもBunで動作します。
1. Bunのインストール
bun
コマンドをインストールするには、公式ウェブサイトの手順に従ってください。
2. セットアップ
2.1. 新規プロジェクトの設定
Bun用のスターターが利用可能です。"bun create"コマンドでプロジェクトを開始します。この例ではbun
テンプレートを選択します。
bun create hono my-app
my-appに移動して、依存関係をインストールします。
cd my-app
bun install
2.2. 既存プロジェクトの設定
既存のBunプロジェクトでは、プロジェクトルートディレクトリでhono
の依存関係をインストールするだけです。
bun add hono
3. Hello World
"Hello World"スクリプトを以下に示します。他のプラットフォームで記述する場合とほぼ同じです。
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Bun!'))
export default app
4. 実行
コマンドを実行します。
bun run dev
次に、ブラウザでhttps://#:3000
にアクセスします。
ポート番号の変更
port
をエクスポートすることで、ポート番号を指定できます。
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
を使用します。
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
https://#:3000/static/*
を./statics
にマップする場合は、rewriteRequestPath
オプションを使用できます。
app.get(
'/static/*',
serveStatic({
root: './',
rewriteRequestPath: (path) =>
path.replace(/^\/static/, '/statics'),
})
)
mimes
mimes
でMIMEタイプを追加できます。
app.get(
'/static/*',
serveStatic({
mimes: {
m3u8: 'application/vnd.apple.mpegurl',
ts: 'video/mp2t',
},
})
)
onFound
要求されたファイルが見つかった場合の処理は、onFound
で指定できます。
app.get(
'/static/*',
serveStatic({
// ...
onFound: (_path, c) => {
c.header('Cache-Control', `public, immutable, max-age=31536000`)
},
})
)
onNotFound
要求されたファイルが見つからない場合の処理は、onNotFound
で指定できます。
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の順に優先されます。いずれも利用できない場合は、元のファイルをサービスします。
app.get(
'/static/*',
serveStatic({
precompressed: true,
})
)
テスト
Bunでテストするには、bun:test
を使用できます。
import { describe, expect, it } from 'bun:test'
import app from '.'
describe('My first test', () => {
it('Should return 200 Response', async () => {
const req = new Request('https://#/')
const res = await app.fetch(req)
expect(res.status).toBe(200)
})
})
次に、コマンドを実行します。
bun test index.test.ts