Node.js

Node.js 是一个开源、跨平台的 JavaScript 运行环境。

Hono 最初并不是为 Node.js 设计的,但通过 Node.js Adapter 它也可以运行在 Node.js 上。

提示 它适用于 Node.js 18.x 及以上版本,具体要求如下:

  • 18.x => 18.14.1+
  • 19.x => 19.7.0+
  • 20.x => 20.0.0+ 基本上,你可以直接使用每个大版本的最新版本。

1. 初始化 (Setup)

Node.js 提供了一个项目模板。使用 create-hono 命令启动你的项目。在这个示例中选择 nodejs 模板。

  1. npm create hono@latest my-app
  1. yarn create hono my-app
  1. pnpm create hono my-app
  1. bun create hono@latest my-app
  1. deno init --npm hono my-app

进入 my-app 目录并安装依赖:

  1. cd my-app
  2. npm i
  1. cd my-app
  2. yarn
  1. cd my-app
  2. pnpm i
  1. cd my-app
  2. bun i

2. Hello World

编辑 src/index.ts

  1. import { serve } from '@hono/node-server'
  2. import { Hono } from 'hono'
  3. const app = new Hono()
  4. app.get('/', (c) => c.text('Hello Node.js!'))
  5. serve(app)

如果需要优雅地关闭服务器,可以这样写:

  1. const server = serve(app)
  2. // graceful shutdown
  3. process.on('SIGINT', () => {
  4. server.close()
  5. process.exit(0)
  6. })
  7. process.on('SIGTERM', () => {
  8. server.close((err) => {
  9. if (err) {
  10. console.error(err)
  11. process.exit(1)
  12. }
  13. process.exit(0)
  14. })
  15. })

3. 运行 (Run)

本地运行开发服务器,然后在浏览器访问 http://localhost:3000。

  1. npm run dev
  1. yarn dev
  1. pnpm dev

修改端口号

可以通过 port 选项指定端口号:

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

访问原生 Node.js API

你可以通过 c.env.incomingc.env.outgoing 访问 Node.js API。

  1. import { Hono } from 'hono'
  2. import { serve, type HttpBindings } from '@hono/node-server'
  3. // 如果使用 HTTP2,可以替换为 `Http2Bindings`
  4. type Bindings = HttpBindings & {
  5. /* ... */
  6. }
  7. const app = new Hono<{ Bindings: Bindings }>()
  8. app.get('/', (c) => {
  9. return c.json({
  10. remoteAddress: c.env.incoming.socket.remoteAddress,
  11. })
  12. })
  13. serve(app)

服务静态文件 (Serve static files)

可以使用 serveStatic 从本地文件系统提供静态文件。例如,目录结构如下:

  1. ./
  2. ├── favicon.ico
  3. ├── index.ts
  4. └── static
  5. ├── hello.txt
  6. └── image.png

当访问 /static/* 路径时,如果你想返回 ./static 目录下的文件,可以这样写:

  1. import { serveStatic } from '@hono/node-server/serve-static'
  2. app.use('/static/*', serveStatic({ root: './' }))

如果想在根目录下提供 favicon.ico,可以这样写:

  1. app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))

如果访问 /hello.txt/image.png 时要返回 ./static/hello.txt./static/image.png,可以这样写:

  1. app.use('*', serveStatic({ root: './static' }))

rewriteRequestPath

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

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

http2

你可以让 Hono 运行在 Node.js http2 Server 上。

未加密的 http2

  1. import { createServer } from 'node:http2'
  2. const server = serve({
  3. fetch: app.fetch,
  4. createServer,
  5. })

加密的 http2

  1. import { createSecureServer } from 'node:http2'
  2. import { readFileSync } from 'node:fs'
  3. const server = serve({
  4. fetch: app.fetch,
  5. createServer: createSecureServer,
  6. serverOptions: {
  7. key: readFileSync('localhost-privkey.pem'),
  8. cert: readFileSync('localhost-cert.pem'),
  9. },
  10. })

构建与部署 (Building & Deployment)

  1. npm run build
  1. yarn run build
  1. pnpm run build
  1. bun run build

提示 带前端框架的应用可能需要使用 Hono 的 Vite 插件

Dockerfile

以下是一个 Node.js 的 Dockerfile 示例:

  1. FROM node:22-alpine AS base
  2. FROM base AS builder
  3. RUN apk add --no-cache gcompat
  4. WORKDIR /app
  5. COPY package*json tsconfig.json src ./
  6. RUN npm ci && \
  7. npm run build && \
  8. npm prune --production
  9. FROM base AS runner
  10. WORKDIR /app
  11. RUN addgroup --system --gid 1001 nodejs
  12. RUN adduser --system --uid 1001 hono
  13. COPY --from=builder --chown=hono:nodejs /app/node_modules /app/node_modules
  14. COPY --from=builder --chown=hono:nodejs /app/dist /app/dist
  15. COPY --from=builder --chown=hono:nodejs /app/package.json /app/package.json
  16. USER hono
  17. EXPOSE 3000
  18. CMD ["node", "/app/dist/index.js"]