Deno

Deno 是一个基于 V8 的 JavaScript 运行时。它不是 Node.js。Hono 也可以运行在 Deno 上。

你可以使用 Hono,通过 TypeScript 编写代码,用 deno 命令运行应用,并部署到 “Deno Deploy”。

1. 安装 Deno

首先,安装 deno 命令。请参考 官方文档

2. 初始化项目

Deno 提供了 Starter 模板。通过以下命令启动项目:

  1. deno init --npm hono my-app

此示例中选择 deno 模板。

进入 my-app 目录。对于 Deno,无需单独安装 Hono。

  1. cd my-app

3. Hello World

编写你的第一个应用:

  1. import { Hono } from 'hono'
  2. const app = new Hono()
  3. app.get('/', (c) => c.text('Hello Deno!'))
  4. Deno.serve(app.fetch)

4. 运行应用

只需运行以下命令:

  1. deno task start

修改端口号

可以通过修改 Deno.serve 参数指定端口号:

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

提供静态文件

要提供静态文件,可以使用从 hono/middleware.ts 导入的 serveStatic

  1. import { Hono } from 'hono'
  2. import { serveStatic } from 'hono/deno'
  3. const app = new Hono()
  4. app.use('/static/*', serveStatic({ root: './' }))
  5. app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))
  6. app.get('/', (c) => c.text('You can access: /static/hello.txt'))
  7. app.get('*', serveStatic({ path: './static/fallback.txt' }))
  8. Deno.serve(app.fetch)

上面的代码适配如下目录结构:

  1. ./
  2. ├── favicon.ico
  3. ├── index.ts
  4. └── static
  5. ├── demo
  6. └── index.html
  7. ├── fallback.txt
  8. ├── hello.txt
  9. └── images
  10. └── dinotocat.png

rewriteRequestPath

如果想把 http://localhost:8000/static/* 映射到 ./statics,可以使用 rewriteRequestPath 选项:

  1. app.get(
  2. '/static/*',
  3. serveStatic({
  4. root: './',
  5. rewriteRequestPath: (path) =>
  6. path.replace(/^\/static/, '/statics'),
  7. })
  8. )

mimes

可以通过 mimes 添加 MIME 类型:

  1. app.get(
  2. '/static/*',
  3. serveStatic({
  4. mimes: {
  5. m3u8: 'application/vnd.apple.mpegurl',
  6. ts: 'video/mp2t',
  7. },
  8. })
  9. )

onFound

可使用 onFound 在文件找到时进行处理:

  1. app.get(
  2. '/static/*',
  3. serveStatic({
  4. onFound: (_path, c) => {
  5. c.header('Cache-Control', `public, immutable, max-age=31536000`)
  6. },
  7. })
  8. )

onNotFound

可使用 onNotFound 在文件未找到时进行处理:

  1. app.get(
  2. '/static/*',
  3. serveStatic({
  4. onNotFound: (path, c) => {
  5. console.log(`${path} is not found, you access ${c.req.path}`)
  6. },
  7. })
  8. )

precompressed

precompressed 选项会检查 .br.gz 等压缩文件,根据 Accept-Encoding 优先返回 Brotli,然后是 Zstd 和 Gzip。没有压缩文件时返回原始文件。

  1. app.get(
  2. '/static/*',
  3. serveStatic({
  4. precompressed: true,
  5. })
  6. )

Deno Deploy

Deno Deploy 是 Deno 的边缘运行平台,可以将应用发布到全球。 Hono 也支持 Deno Deploy。更多详情请查看 官方文档

测试

Deno 的测试非常简单,可以使用 Deno.test@std/assert 中的 assertassertEquals

安装断言库:

  1. deno add jsr:@std/assert

示例测试:

  1. import { Hono } from 'hono'
  2. import { assertEquals } from '@std/assert'
  3. Deno.test('Hello World', async () => {
  4. const app = new Hono()
  5. app.get('/', (c) => c.text('Please test me'))
  6. const res = await app.request('http://localhost/')
  7. assertEquals(res.status, 200)
  8. })

运行测试:

  1. deno test hello.ts

npm: 规范

npm:hono 也可用。可通过修改 deno.json 使用:

  1. {
  2. "imports": {
  3. "hono": "jsr:@hono/hono"
  4. "hono": "npm:hono"
  5. }
  6. }

你可以使用 npm:honojsr:@hono/hono

如果要使用第三方 Middleware,例如 npm:@hono/zod-validator,并需要 TypeScript 类型推导,就必须使用 npm: 规范。

  1. {
  2. "imports": {
  3. "hono": "npm:hono",
  4. "zod": "npm:zod",
  5. "@hono/zod-validator": "npm:@hono/zod-validator"
  6. }
  7. }