[READ-ONLY] Mirror of https://github.com/crutchcorn/hono-node-workers-server. Node.js Worker Threads runtime adapter for Hono.
TypeScript 94%
JavaScript 6%

README.md

hono-node-workers-server #

Node.js Worker Threads runtime adapter for Hono.

This adapter keeps Hono routing and middleware in the main thread, then runs selected route logic in a new Node.js Worker for each request. Worker route modules use Web-standard Request and Response objects so the route logic stays easy to port to other Hono runtimes.

Requirements #

  • Node.js 22+
  • Hono 4+

Server #

import { Hono } from 'hono'
import { serve, workerRoute } from 'hono-node-workers-server'

const app = new Hono()

app.get(
  '/hello/:name',
  workerRoute(new URL('./routes/hello.mjs', import.meta.url), {
    env: () => ({ greeting: 'Hello' }),
  })
)

serve({ fetch: app.fetch, port: 3000 })

Worker Route #

import { defineWorkerRoute } from 'hono-node-workers-server/worker'

export default defineWorkerRoute(async (request, context) => {
  const url = new URL(request.url)

  return Response.json({
    greeting: context.env.greeting,
    name: context.params.name,
    excited: url.searchParams.get('excited') === 'true',
  })
})

The worker route file must be importable by a plain Node.js worker. In practice, point workerRoute() at compiled JavaScript, an .mjs file, or another module Node can import directly.

Portability #

Worker route modules are just fetch-style handlers. To run the same logic in a normal Hono route, call it from a Hono handler:

import hello from './routes/hello.mjs'

app.get('/hello/:name', (c) => {
  return hello(c.req.raw, {
    params: c.req.param(),
    env: { greeting: 'Hello' },
  })
})

API #

serve(options, listeningListener?) #

Starts a Node HTTP server.

serve({ fetch: app.fetch, port: 3000 })

createAdaptorServer(options) #

Creates a Node HTTP server without calling .listen().

const server = createAdaptorServer({ fetch: app.fetch })

workerRoute(moduleSpecifier, options?) #

Creates a Hono middleware handler that runs the route module in a fresh Worker Thread.

workerRoute(new URL('./routes/echo.mjs', import.meta.url), {
  exportName: 'default',
  env: (c) => ({ requestId: c.req.header('x-request-id') }),
  timeoutMs: 1000,
})

Options:

  • exportName: export to call from the worker module. Defaults to default.
  • env: selects cloneable data to pass as context.env. If omitted, context.env is undefined.
  • timeoutMs: aborts the worker if it does not produce a response in time.

Current Limitations #

  • A new Worker Thread is created for each request. There is no worker pool yet.
  • Only HTTP/1 is implemented.
  • WebSockets are not implemented.
  • context.env must be structured-cloneable. Use options.env to select only the data a worker route needs.
  • Request and Response objects are serialized across the worker boundary; Node cannot clone them directly.