Node.js â
Node.js is an open-source, cross-platform JavaScript runtime environment.
Hono was not designed for Node.js at first, but with a Node.js Adapter, it can run on Node.js as well.
INFO
It works on Node.js versions greater than 18.x. The specific required Node.js versions are as follows:
- 18.x => 18.14.1+
- 19.x => 19.7.0+
- 20.x => 20.0.0+
Essentially, you can simply use the latest version of each major release.
1. Setup â
A starter for Node.js is available. Start your project with "create-hono" command. Select nodejs template for this example.
npm create hono@latest my-appyarn create hono my-apppnpm create hono my-appbun create hono@latest my-appdeno init --npm hono my-appMove to my-app and install the dependencies.
cd my-app
npm icd my-app
yarncd my-app
pnpm icd my-app
bun i2. Hello World â
Edit 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)If you want to gracefully shut down the server, write it like this:
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)
})
})3. Run â
Run the development server locally. Then, access http://localhost:3000 in your Web browser.
npm run devyarn devpnpm devChange port number â
You can specify the port number with the port option.
serve({
fetch: app.fetch,
port: 8787,
})Access the raw Node.js APIs â
You can access the Node.js APIs from c.env.incoming and 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)Serve static files â
You can use serveStatic to serve static files from the local file system. For example, suppose the directory structure is as follows:
./
âââ favicon.ico
âââ index.ts
âââ static
âââ hello.txt
âââ image.pngIf a request to the path /static/* comes in and you want to return a file under ./static, you can write the following:
import { serveStatic } from '@hono/node-server/serve-static'
app.use('/static/*', serveStatic({ root: './' }))WARNING
The root option resolves paths relative to the current working directory (process.cwd()). This means the behavior depends on where you run your Node.js process from, not where your source file is located. If you start your server from a different directory, file resolution may fail.
For reliable path resolution that always points to the same directory as your source file, use 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)) })
)Use the path option to serve favicon.ico in the directory root:
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))If a request to the path /hello.txt or /image.png comes in and you want to return a file named ./static/hello.txt or ./static/image.png, you can use the following:
app.use('*', serveStatic({ root: './static' }))rewriteRequestPath â
If you want to map http://localhost:3000/static/* to ./statics, you can use the rewriteRequestPath option:
app.get(
'/static/*',
serveStatic({
root: './',
rewriteRequestPath: (path) =>
path.replace(/^\/static/, '/statics'),
})
)http2 â
You can run hono on a Node.js http2 Server.
unencrypted http2 â
import { createServer } from 'node:http2'
const server = serve({
fetch: app.fetch,
createServer,
})encrypted http2 â
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'),
},
})Building & Deployment â
npm run buildyarn run buildpnpm run buildbun run buildINFO
Apps with a front-end framework may need to use Hono's Vite plugins.
Dockerfile â
Here is an example of a 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"]