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.
npm create hono@latest my-appyarn create hono my-apppnpm create hono my-appbun create hono@latest my-appdeno init --npm hono my-appOuvrez my-app et installez les dépendances.
cd my-app
npm icd my-app
yarncd my-app
pnpm icd my-app
bun i2. Bonjour le monde
Modifiez src/index.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 :
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.
npm run devyarn devpnpm devModifier le numéro de port
Vous pouvez préciser le numéro de port avec l'option port.
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.
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.
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 :
./
├── favicon.ico
├── index.ts
└── static
├── hello.txt
└── image.pngPour une requête vers le chemin /static/*, si vous souhaitez renvoyer un fichier sous ./static, écrivez :
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 :
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 :
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 :
app.use('*', serveStatic({ root: './static' }))rewriteRequestPath
Si vous souhaitez faire correspondre http://localhost:3000/static/* à ./statics, utilisez l'option rewriteRequestPath :
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é
import { createServer } from 'node:http2'
const server = serve({
fetch: app.fetch,
createServer,
})http2 chiffré
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
npm run buildyarn run buildpnpm run buildbun run buildInformation
Les applications utilisant un framework front-end peuvent avoir besoin des plugins Vite de Hono.
Dockerfile
Voici un exemple de Dockerfile pour Node.js.
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"]