本文へ移動

Deno ​

Deno は V8 を基盤とする JavaScript ランタイムで、Node.js とは異なります。 Hono は Deno 上でも動作します。

Hono を使って TypeScript でコードを記述し、deno コマンドで実行して、「Deno Deploy」にデプロイできます。

1. Deno のインストール ​

まず、deno コマンドをインストールします。 公式ドキュメントを参照してください。

2. セットアップ ​

Deno 向けのスターターテンプレートがあります。 deno init コマンドでプロジェクトを開始します。

sh
deno init --npm hono --template=deno my-app

my-app に移動します。Deno では Hono を明示的にインストールする必要はありません。

sh
cd my-app

3. Hello World ​

main.ts を編集します。

main.ts
ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => c.text('Hello Deno!'))

Deno.serve(app.fetch)

4. 実行 ​

開発サーバーをローカルで起動し、Web ブラウザーで http://localhost:8000 にアクセスします。

sh
deno task start

ポート番号の変更 ​

main.ts の Deno.serve の引数を変更すると、ポート番号を指定できます。

ts
Deno.serve(app.fetch) 
Deno.serve({ port: 8787 }, app.fetch) 

静的ファイルの配信 ​

静的ファイルを配信するには、@hono/deno パッケージの serveStatic を使います。

sh
deno add jsr:@hono/deno
ts
import { Hono } from 'hono'
import { serveStatic } from '@hono/deno'

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' }))

Deno.serve(app.fetch)

上記のコードは、次のディレクトリ構成で動作します。

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

rewriteRequestPath ​

http://localhost:8000/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,
  })
)

Deno Deploy ​

Deno Deploy は、クラウドで JavaScript と TypeScript のアプリケーションを実行するサーバーレスプラットフォームです。 GitHub デプロイなどの連携を通じて、アプリケーションをデプロイし実行するための管理基盤を提供します。

Hono は Deno Deploy 上でも動作します。公式ドキュメントを参照してください。

テスト ​

Deno 上でアプリケーションをテストするのは簡単です。 Deno.test でテストを記述し、@std/assert の assert や assertEquals を使えます。

sh
deno add jsr:@std/assert
hello.ts
ts
import { Hono } from 'hono'
import { assertEquals } from '@std/assert'

Deno.test('Hello World', async () => {
  const app = new Hono()
  app.get('/', (c) => c.text('Please test me'))

  const res = await app.request('http://localhost/')
  assertEquals(res.status, 200)
})

続いて、次のコマンドを実行します。

sh
deno test hello.ts

npm と JSR ​

Hono は npm と JSR(JavaScript Registry)の両方で提供されています。deno.json で npm:hono または jsr:@hono/hono を使えます。

json
{
  "imports": {
    "hono": "jsr:@hono/hono"
    "hono": "npm:hono"
  }
}

ミドルウェアを使うには、インポートに Deno ディレクトリの構文を使う必要があります。

json
{
  "imports": {
    "hono/": "npm:/hono/"
  }
}

サードパーティのミドルウェアを使う場合、TypeScript の型を正しく推論するため、ミドルウェアと同じレジストリの Hono を使う必要がある場合があります。たとえば、npm のミドルウェアを使うなら、Hono も npm から使います。

json
{
  "imports": {
    "hono": "npm:hono",
    "zod": "npm:zod",
    "@hono/zod-validator": "npm:@hono/zod-validator"
  }
}

JSR でも多数のサードパーティのミドルウェアパッケージを提供しています。JSR のミドルウェアを使う場合は、Hono も JSR から使います。

json
{
  "imports": {
    "hono": "jsr:@hono/hono",
    "zod": "npm:zod",
    "@hono/zod-validator": "jsr:@hono/zod-validator"
  }
}

MIT ライセンスで公開されています。