github nitrojs/nitro v3.0.260903-beta

4 hours ago

Note

Thi release focuses on security hardenings, bug fixes, better observability, and a more reliable development experience.

Many of new improvements are from major dependency upgrades (h3, srvx, rou3, ocache, db0, env-runner, unctx and unwasm) plus the work in Nitro to adopt them. The sections below group the changes by what they mean for your app.

πŸš€ What’s new

🧭 Routing and route rules

Nitro migrated to the new route rules engine from h3, backed by rou3 v0.9. See the Nitro routing guide and h3 route rules guide. (#4411)

  • Rules are matched on the canonical path, with sibling routes ordered by specificity. (#4396)
  • GET routes automatically answer HEAD requests.
  • New cors rule replaces manual CORS wiring: { "/api/**": { cors: true } }.
  • basicAuth route rules are replaced by middleware (see After you upgrade).

πŸ’Ύ Caching

defineCachedHandler, defineCachedFunction and cache route rules now run on ocache v0.3 (up from 0.1), which brings safer defaults, bounded memory and several new capabilities. Please review your caching configuration β€” defaults changed. See Review your caching configuration and the Nitro caching guide.

πŸ—„οΈ Database

Nitro now uses db0 v0.4. Database client libraries are passed explicitly to connectors; Nitro handles this for configured connectors and prompts to install what is missing. New in this line: neon, prisma and libsql-core connectors, Kysely integration, database capabilities metadata, and tracing channel support. See the Nitro database guide, db0 connectors, and db0 integrations.

πŸ”Œ WebSockets

WebSocket support moves to crossws 0.4.12 (from 0.4.6), which adds a batch of features usable from Nitro WebSocket handlers. See the Nitro WebSocket guide.

  • Liveness: universal idleTimeout to detect half-open connections, application-level ping/pong hooks and peer.ping(). (#201, #202)
  • Backpressure: peer.bufferedAmount (docs) and opt-in subprotocol negotiation. (#195, #203)
  • Pub/sub: a sync backplane to share channels across instances (docs), plus auth and context support. (#192, #112)

πŸ”­ Observability and tracing

πŸ”’ Security

  • h3 has undergone several rounds of security hardening audits (path normalization, forwarded headers, host header handling, cookies, CORS, basic auth, JSON-RPC, session sealing).
  • Development task endpoints (/_nitro/tasks and /_nitro/tasks/:name) now accept only local requests. This prevents remote clients with access to the dev server from listing or invoking tasks. (#4389)
  • Cached responses no longer replay cookies by default.
  • Better static file responses: conditional requests with ETag and Last-Modified, byte ranges, optional Cache-Control, and additional path-traversal hardening.

⚑ Faster and more reliable

  • Improved alias resolution, development sourcemaps, request middleware, and logging.
  • Development worker reloads are serialized and cleanly awaited, stale module caches are cleared, (vite) aliases apply in the correct order, base paths are respected, and ?import requests remain handled by Vite.
  • Static presets no longer create an unnecessary server bundle.

πŸ“ Import any file as bytes or text

In server bundle: (#4431)

  import logo from "./logo.png" with { type: "bytes" }; // Uint8Array
  import readme from "./README.md" with { type: "text" }; // string

πŸ“¦ No more peer dependencies

Nitro no longer has any peer dependencies. Features that need an extra package (a builder, a preset, a storage driver, a database connector) resolve it from your project, and Nitro prompts to install anything missing. In CI, missing packages are installed automatically. Existing projects need no changes when the required packages are already installed. (#4542, #4543)

Nitro also validates the version of what it finds and warns when an installed package is outside the supported range. Supported builders are vite@^7 || ^8, rollup@^4 and rolldown@>=1.0.0. (87219b2)

Leaner install

Alongside dropping peer dependencies, several packages were removed from Nitro entirely: tsconfck (replaced by get-tsconfig), magic-string, uncrypto, serve-placeholder, edge-runtime, @types/http-proxy and @types/node-fetch. ofetch is no longer a runtime dependency, and rou3 is now a direct dependency instead of being pulled in indirectly.

☁️ Presets

  • Cloudflare: local development now uses Miniflare/workerd directly, with bindings available on the request event. Nitro offers to install miniflare when first needed. See the Nitro Cloudflare guide. (#4338)
  • Vercel: set vercel.immutableStaticFiles: true to emit content-hashed static files with immutable caching. See the Nitro Vercel guide. (#4432)
  • Netlify Edge: keeps dynamic imports lazy, reducing cold-start work for lazy handlers and deferred WASM initialization. (#4525)

⚠️ Migration

Routing

  • Replace basicAuth route rules with middleware.

    import { defineHandler } from "nitro";
    import { basicAuth } from "nitro/h3";
    
    export default defineHandler({
      middleware: [basicAuth({ username: "admin", password: "supersecret" })],
      handler: (event) => `Hello, ${event.context.basicAuth?.username}!`,
    });

    To protect multiple routes, register route-scoped middleware or add it under middleware/.

  • Use the new cors rule where needed: { "/api/**": { cors: true } }.

  • Update renamed types when convenient: NitroRouteConfig and NitroRouteRules are deprecated aliases for RouteRuleConfig and NormalizedRouteRules. The old names are still exported from nitro/types.

Review your caching configuration

The upgrade from ocache 0.1 to 0.3 introduces safer defaults for defineCachedHandler, defineCachedFunction, and cache route rules:

  • swr now defaults to false, so expired entries are refreshed before returning. Set swr: true to keep background revalidation. The swr route-rule shortcut already does this.
  • Query parameters are ignored by default. Set allowQuery: true or list the parameters that should affect the cache key.
  • Cookies are removed from cached requests and responses unless listed in allowCookies; responses containing Set-Cookie are not cached.
  • GET and HEAD now use separate cache entries.
  • Cache keys now include the request authority, and undeclared request headers are hidden from handlers.
  • Cache resolution has a new 30-second timeout (maxResolveTime), and memory storage is limited by bytes.

See the ocache migration guide for details.


πŸ“¦ Major dependency updates

Package From To Release notes
h3 2.0.1-rc.22 ^2.0.1-rc.29 rc.23 … rc.29
srvx ^0.11.16 ^0.12.7 v0.12.0
rou3 ^0.8.1 ^0.9.2 v0.9.0
db0 ^0.3.4 ^0.4.0 v0.4.0
env-runner ^0.1.12 ^0.2.0 v0.2.0
ocache ^0.1.5 ^0.3.0 v0.2.0, v0.3.0 β€” crosses two lines
unctx ^2.5.0 ^3.0.1 v3.0.0
unwasm ^0.5.3 ^0.6.0 v0.6.0

h3

  • New route rules engine (#1524, docs) β€” what Nitro's route rules now build on.
  • New request features: QUERY method support, automatic HEAD matching for GET routes, requireContentType and appendAcceptQuery, formdata in readBody, async validation in defineValidatedHandler, an onDispose hook, and returning an EventStream directly from handlers. See the h3 request utilities.
  • Sessions: default SameSite=Lax cookie, PBKDF2 seal iterations raised to 8192, and opt-in idleTimeout for sliding expiration. See the h3 session example.
  • Performance: precomposed middleware chains, streaming body-limit enforcement, faster path normalization and cookie parsing.
  • Security: escaped interpolation in the html template tag, hop-aware x-forwarded-* handling, host header no longer steers the synthesized URL, stricter percent-decoding and canonical-path checks in static serving, hardened basic auth and JSON-RPC, and safer CORS Vary/credential handling. See the h3 security utilities.

srvx

  • Static files: security hardening, ETag + Last-Modified conditional requests, byte-range support, and opt-in Cache-Control via maxAge/immutable. (#252, #269, #273, #275)
  • Performance: the middleware chain is precomposed at construction time and stdout writes are batched with a cached timestamp.
  • Node adapter correctness: bridged responses stream instead of buffering, hop-by-hop headers are stripped, HEAD bodies are discarded, client aborts destroy the body stream, and unhandled handler errors answer 500.
  • New: body size limit helpers via srvx/body-limit (docs).
  • ⚠️ Subpath exports were renamed to *Middleware / *Plugin (#278).

rou3

  • Route pattern overlap utilities (#183) and regExpToRoute() to convert PCRE regex back to a route pattern (#188).
  • findAllRoutes aligned with findRoute and compiled matchAll, with same-node siblings ordered by specificity.

db0

See the Nitro database guide and the db0 connector reference.

  • ⚠️ Connectors require the client library to be passed explicitly. Nitro does this for connectors you configure, and prompts to install the missing package.
  • New neon (serverless postgres), prisma and libsql-core connectors, plus a Kysely integration.
  • Database capabilities metadata and exposed connector name.
  • Tracing channel support (feeds the new tracing logger).
  • ⚠️ Drizzle upgraded to v1, with schema parameter support and updated postgres/mysql connectors.

ocache

See the Nitro caching guide and ocache migration guide.

New in this line, beyond the default changes listed above:

  • Layered and binary-friendly storage: composeStorage for fast + persistent backends, native binary payloads without base64, binary function results, and createBlobStorage.
  • Latency and background work: opt into stream to serve a cache fill while it is still buffering, and waitUntil for background tasks.
  • New hooks and options: getMaxAge (per-entry TTL), serialize, shouldCache, async validate, sendCacheControl: false, and .expire() / .invalidate() / .resolveKeys() on cached handlers.
  • Automatic headers: Vary emission for your varies config and an x-cache status header (hit / stale / revalidated / miss).
  • Runtime-independent hashing: deterministic SHA-256 based hashing with stronger collision protection and no runtime dependencies.

env-runner

See the Nitro Cloudflare guide.

  • ⚠️ Runtime dependencies are now explicit β€” Nitro offers to install miniflare the first time Cloudflare local development needs it.

unctx (async context)

  • Defaults to the built-in AsyncLocalStorage.
  • Transform moved to oxc, skips files without await, and precomputes line offsets.
  • Fixes an instance leak via AsyncLocalStorage using WeakRef.

unwasm (WASM support)

See the unwasm documentation.

  • ⚠️ webassemblyjs replaced with a built-in WASM parser (#104) β€” fewer dependencies and a lighter install.

Full changelog

compare changes

πŸš€ Enhancements

  • Experimental tracing logger (#4406)
  • routing: Migrate route rules to h3-rules (#4411)
  • build: Support bytes and text import attributes (#4431)
  • ⚠️ Migrate to h3/rules (f70163c3)
  • Prompt to install storage driver dependencies (89bda739)
  • Migrate env-runner to 0.2 with explicit deps (5060305f)
  • Upgrade to db0 0.4 (d435e8c9)
  • vite: Import vite on demand from the user project (#4543)

πŸ”₯ Performance

  • build: Only cross-resolve internal aliases (#4371)
  • dev: Cache sourcemap consumer per bundle in error handler (#4454)
  • app: Compose the middleware chain once instead of per request (#4559)

🩹 Fixes

  • vite: Handle explicit public asset dirs (7765bcb7)
  • vite: Close env runner during Vite environment cleanup (#4362)
  • config: Detect vite.config.c[jt]s (#4363)
  • rolldown: Disable built-in tsconfig loader (#4369)
  • vite: Generate nitro types in vite builder (#4387)
  • dev: Restrict /_nitro/tasks endpoint to local requests (#4389)
  • vite: Respect bun/deno export conditions in dev server (#4397)
  • route-meta: Add order:pre to route-meta plugin hooks (#4316)
  • Match route rules on canonical path (#4396)
  • externals: Force-trace named traceDeps to fix pnpm nested deps (#4391)
  • externals: Only force-trace observed native imports (#4420)
  • vercel: Use SameSite=Lax for skew protection cookie (#4422)
  • vite: Respect apply and dedupe when registering nitro modules from vite plugins (#4430)
  • vite: Route asset-tagged requests to opaque catch-alls in dev (#4467)
  • vite: Keep ?import module requests on vite in dev (#4453)
  • vite: Subscribe rollup:reload to hot-reload after updateConfig (#4503)
  • presets: Keep srvx/body-limit out of the bare srvx alias (#4538)
  • externals: Skip bare scopes as unresolvable (69c36aa8)
  • build: Namespace virtual module ids in sourcemap sources (f135ec84)
  • vite: Always remove deprecated inlineDynamicImports (23c93b07)
  • vite: Make dev middleware Vite-internal prefix checks base-aware (#4540)
  • vite: Pass aliases as ordered entries so specific keys win (#4537)
  • rollup: Emit import attributes with the with key (#4520)
  • netlify: Enable code-splitting for the netlify-edge preset (#4525)
  • vercel: Preserve relative function symlinks (#4490)
  • dev: Await worker shutdown before replacing it (#4506)
  • cloudflare: Omit worker entry from wrangler.json for static builds (#4255)
  • vercel: Strip trailing slash from prerendered route overrides (#4412)
  • vite: Skip server bundle for static presets (#4509)
  • vite: Serialize dev worker reloads (#4541)
  • vite: Clear module runner cache before dev worker reload (#4473)
  • config: Resolve default server assets dir from serverDir (#4562)
  • routing: Respect baseURL for single catch-all routes (#4561)
  • routing: Serialize route-scoped middleware as plain handlers (#4558)
  • vercel: Correct ISR route rewrite query preservation and decoding (#4409)
  • presets: Call runtime close hooks on server shutdown (#4574)
  • build: Count each output file once in the size report (#4568)
  • build: Pass the real request to node format handlers (e5de9849)
  • cloudflare: Correctly traverse baseURL segments when computing assets directory (#4257)
  • rollup: Escape dynamic route segments in chunk names (#4508)
  • vercel, netlify, edgeone: Expand ** anywhere in redirect and proxy targets (066510fd)
  • cloudflare: Do not rewrite createRequire or node imports inside strings (#4535)
  • vercel: Prevent caching missing public assets (#4474)
  • storage, database: Import connector libs from their real specifier (8157e00b)
  • deps: Auto-install in agent and non-tty environments (a28ca29f)

πŸ’… Refactors

  • Replace deprecated tsconfck with get-tsconfig (#4367)
  • build: Disable rolldown internal export minification (#4368)
  • deno: Use default node handler for serveStatic (#4398)
  • Improve logging plugin responsiveness (f3a1aa6d)
  • deps: Import optional deps on demand from the user project (#4542)
  • dep: Version validation (87219b2a)
  • Use node hash (923f3c28)
  • types: ⚠️ Remove typed fetch (#4572)
  • ⚠️ Remove auto imports (#4573)
  • ⚠️ Remove type generation (#4577)

πŸ“– Documentation

  • vercel: Fix queues examples for nitro v3 api (#4374)
  • Fix grammer issue in landing (#4382)
  • Use variable font weight range for geist (#4383)
  • Update zerops provider docs (#4380)
  • Add defineNitroPlugin to migration guide (#4400)
  • examples: Add takumi og image example (#4421)
  • Use event.url.pathname in lifecycle hook examples (#4442)
  • Fix link navigation (#4444)
  • Clarify database connection options shape (#4465)
  • Update to last undocs (#4524)
  • Add missing redirects (16ff2809)
  • Update landing (46a6fcaf)
  • List supported configuration file names (#4517)
  • Improvements (#4426)
  • Document minify: false for debugging workers (#4452)
  • Clarify route-scoped middleware example path (#4445)

πŸ“¦ Build

  • Point root types to published declaration (#4347)
  • Remove ofetch from deps (f9091c14)
  • Re-export FastResponse and srvx types (#4499)
  • Externalize cjs declarations (f930cda7)

🌊 Types

  • Export missing h3 types from runtime (#4378)
  • Use CachedFunction return type for defineCachedFunction (#4377)
  • vite: Use named types for fetchable dev environment (78437e1c)
  • config: Map builtin driver and connector options (#4571)
  • Widen RollupConfig.plugins to accept rolldown-typed plugins (#4483)

βœ… Tests

  • public-assets: Cover node reader path resolution and traversal safety (65d275b7)
  • Add local wasm fixture (af70f2d7)
  • Bump bundle sizes (a2528959)
  • Silent logs (96607689)

πŸ€– CI

  • Improve actions workflows (#4388)
  • Run pkg.pr.new after lint (11b4761a)

Preset Changes

  • cloudflare: Use env-runner/miniflare for local dev and update docs (#4338)
  • vercel: Use reflinks for custom function dirs (#4373)
  • vercel: Export tracing channels messages as otlp spans (#4355)
  • cloudflare: Bridge tracing channel events to observability custom spans (#4413)
  • Update winterjs (a1cac7d7)
  • vercel: Support immutable static files (#4432)
  • vercel: Do not generate observability functions with fully prerendered routes (#4497)
  • aws-lambda: Switch to srvx (#4056)

❀️ Contributors

Don't miss a new nitro release

NewReleases is sending notifications on new releases.