Aller au contenu

Node.js ​

Node.js est un environnement d'exécution JavaScript open source et multiplateforme.

Hono n'a pas été conçu initialement pour Node.js, mais un adaptateur Node.js lui permet aussi de s'y exécuter.

Information

Il fonctionne avec Node.js à partir de la branche 18.x. Les versions minimales requises sont les suivantes :

  • 18.x => 18.14.1+
  • 19.x => 19.7.0+
  • 20.x => 20.0.0+

Vous pouvez donc simplement utiliser la dernière version de chaque version majeure.

1. Configuration ​

Un modèle de démarrage est disponible pour Node.js. Créez votre projet avec la commande « create-hono ». Sélectionnez le modèle nodejs pour cet exemple.

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

Ouvrez my-app et installez les dépendances.

sh
cd my-app
npm i
sh
cd my-app
yarn
sh
cd my-app
pnpm i
sh
cd my-app
bun i

2. Bonjour le monde ​

Modifiez src/index.ts :

ts
import { serve } from '@hono/node-server'
import { Hono } from 'hono'

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

serve(app)

Pour arrêter proprement le serveur, écrivez comme suit :

ts
const server = serve(app)

// graceful shutdown
process.on('SIGINT', () => {
  server.close()
  process.exit(0)
})
process.on('SIGTERM', () => {
  server.close((err) => {
    if (err) {
      console.error(err)
      process.exit(1)
    }
    process.exit(0)
  })
})

Information

Sur Node.js, serve() encapsule le module node:http et renvoie l'instance du serveur sous-jacent ; sa fermeture vous revient donc. Bun et Deno prennent nativement en charge les gestionnaires Fetch et gèrent eux-mêmes le serveur, ce qui explique l'absence de cette étape dans leurs guides.

3. Exécution ​

Démarrez le serveur de développement localement. Ensuite, ouvrez http://localhost:3000 dans votre navigateur web.

sh
npm run dev
sh
yarn dev
sh
pnpm dev

Modifier le numéro de port ​

Vous pouvez préciser le numéro de port avec l'option port.

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

WebSocket ​

La prise en charge de WebSocket est intégrée à @hono/node-server. Installez ws et, si vous utilisez TypeScript, @types/ws. Créez ensuite un WebSocketServer avec { noServer: true } et passez-le à serve() via l'option websocket.

@hono/node-ws est obsolète.

ts
import { serve, upgradeWebSocket } from '@hono/node-server'
import { Hono } from 'hono'
import { WebSocketServer } from 'ws'

const app = new Hono()

app.get(
  '/ws',
  upgradeWebSocket(() => ({
    onMessage(event, ws) {
      ws.send(event.data)
    },
  }))
)

const wss = new WebSocketServer({ noServer: true })

serve({
  fetch: app.fetch,
  websocket: { server: wss },
})

Accéder aux API Node.js brutes ​

Vous pouvez accéder aux API Node.js depuis c.env.incoming et c.env.outgoing.

ts
import { Hono } from 'hono'
import { serve, type HttpBindings } from '@hono/node-server'
// or `Http2Bindings` if you use HTTP2

type Bindings = HttpBindings & {
  /* ... */
}

const app = new Hono<{ Bindings: Bindings }>()

app.get('/', (c) => {
  return c.json({
    remoteAddress: c.env.incoming.socket.remoteAddress,
  })
})

serve(app)

Servir des fichiers statiques ​

Vous pouvez utiliser serveStatic pour servir des fichiers statiques depuis le système de fichiers local. Supposons par exemple l'arborescence suivante :

sh
./
├── favicon.ico
├── index.ts
└── static
    ├── hello.txt
    └── image.png

Pour une requête vers le chemin /static/*, si vous souhaitez renvoyer un fichier sous ./static, écrivez :

ts
import { serveStatic } from '@hono/node-server/serve-static'

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

Attention

L'option root résout les chemins par rapport au répertoire de travail courant (process.cwd()). Le comportement dépend donc du répertoire depuis lequel vous lancez le processus Node.js, et non de l'emplacement du fichier source. Si vous démarrez le serveur depuis un autre répertoire, la résolution des fichiers peut échouer.

Pour une résolution fiable qui pointe toujours vers le répertoire du fichier source, utilisez import.meta.url :

ts
import { fileURLToPath } from 'node:url'
import { serveStatic } from '@hono/node-server/serve-static'

app.use(
  '/static/*',
  serveStatic({ root: fileURLToPath(new URL('./', import.meta.url)) })
)

Utilisez l'option path pour servir favicon.ico à la racine du répertoire :

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

Pour une requête vers /hello.txt ou /image.png, si vous souhaitez renvoyer le fichier ./static/hello.txt ou ./static/image.png, utilisez :

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

rewriteRequestPath ​

Si vous souhaitez faire correspondre http://localhost:3000/static/* à ./statics, utilisez l'option rewriteRequestPath :

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

http2 ​

Vous pouvez exécuter Hono sur un serveur http2 Node.js.

http2 non chiffré ​

ts
import { createServer } from 'node:http2'

const server = serve({
  fetch: app.fetch,
  createServer,
})

http2 chiffré ​

ts
import { createSecureServer } from 'node:http2'
import { readFileSync } from 'node:fs'

const server = serve({
  fetch: app.fetch,
  createServer: createSecureServer,
  serverOptions: {
    key: readFileSync('localhost-privkey.pem'),
    cert: readFileSync('localhost-cert.pem'),
  },
})

Compilation et déploiement ​

sh
npm run build
sh
yarn run build
sh
pnpm run build
sh
bun run build

Information

Les applications utilisant un framework front-end peuvent avoir besoin des plugins Vite de Hono.

Dockerfile ​

Voici un exemple de Dockerfile pour Node.js.

Dockerfile
FROM node:22-alpine AS base

FROM base AS builder

RUN apk add --no-cache gcompat
WORKDIR /app

COPY package*json tsconfig.json src ./

RUN npm ci && \
    npm run build && \
    npm prune --production

FROM base AS runner
WORKDIR /app

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 hono

COPY --from=builder --chown=hono:nodejs /app/node_modules /app/node_modules
COPY --from=builder --chown=hono:nodejs /app/dist /app/dist
COPY --from=builder --chown=hono:nodejs /app/package.json /app/package.json

USER hono
EXPOSE 3000

CMD ["node", "/app/dist/index.js"]

Publié sous licence MIT.