diff --git a/docs/1.guide/2.routing.md b/docs/1.guide/2.routing.md index d7de046c97..a2d4e589d4 100644 --- a/docs/1.guide/2.routing.md +++ b/docs/1.guide/2.routing.md @@ -275,6 +275,7 @@ This behaviour can be overridden by some request properties (e.g.: `Accept` or ` Nitro allows you to add logic at the top-level for each route of your configuration. It can be used for redirecting, proxying, caching and adding headers to routes. It is a map from route pattern (following [radix3](https://github.com/unjs/rou3/tree/radix3#route-matcher)) to route options. +All matching rules are deep‑merged with specificity precedence (more specific patterns override less specific), and matching is based on the path only (no query string). When `cache` option is set, handlers matching pattern will be automatically wrapped with `defineCachedEventHandler`. See the [cache guide](/guide/cache) to learn more about this function. @@ -318,3 +319,190 @@ export default defineNuxtConfig({ }) ``` :: + +::note +Nuxt adds additional route rules such as `ssr`, `noScripts`, and `appMiddleware` that affect HTML rendering behavior inside the Vue app. See Nuxt docs for details. +:: + +#### Cache + +Server-side response caching for matching routes. If set to `false`, disables server-side caching. See: [Cache guide](/guide/cache) + +**Example:** + +::code-group +```ts [nitro.config.ts] +export default defineNitroConfig({ + routeRules: { + '/**': { cache: { swr: true, maxAge: 60 } } + } +}) +``` + +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + routeRules: { + '/**': { cache: { swr: true, maxAge: 60 } } + } +}) +``` +:: + +::note +Shortcut: `swr` below sets `cache: { swr: true, maxAge?: number }`. +:: + +#### Headers + +An object of response headers to set for matching routes. + +**Example:** + +::code-group +```ts [nitro.config.ts] +export default defineNitroConfig({ + routeRules: { + '/**': { headers: { + "Cross-Origin-Resource-Policy": "same-site", + "Cross-Origin-Embedder-Policy": "require-corp", + "Cross-Origin-Opener-Policy": "same-origin" + } + } + } +}) +``` + +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + routeRules: { + '/**': { headers: { + "Cross-Origin-Resource-Policy": "same-site", + "Cross-Origin-Embedder-Policy": "require-corp", + "Cross-Origin-Opener-Policy": "same-origin" + } + } + } +}) +``` +:: + +#### Redirect + +Server-side redirect. A plain string uses status code 307 by default. +If the rule key ends with `/**` and `to` also ends with `/**`, the matched tail of the path is appended to `to`. Query params are preserved when the destination is not a wildcard pattern. + +**Example:** + +::code-group +```ts [nitro.config.ts] +export default defineNitroConfig({ + routeRules: { + '/foo': { redirect: '/bar' }, + 'baz/**': { redirect: { to: '/qux/**', statusCode: 301 } } + } +}) +``` + +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + routeRules: { + '/foo': { redirect: '/bar' }, + 'baz/**': { redirect: { to: '/qux/**', statusCode: 301 } } + } +}) +``` +:: + + +#### Prerender + +Adds exact paths to the prerender queue at build time so they are emitted as static assets. + + +**Example:** + +::code-group +```ts [nitro.config.ts] +export default defineNitroConfig({ + routeRules: { + '/': { prerender: true } + } +}) +``` + +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + routeRules: { + '/': { prerender: true } + } +}) +``` +:: + +#### Proxy + +Proxies matching requests to another origin or internal path. +If the rule key ends with `/**` and `to` also ends with `/**`, the matched tail of the path is appended to `to`. Query params are preserved when the destination is not a wildcard pattern. +For proxy options, see [H3](https://github.com/h3js/h3/blob/ec77d6bc148e4ff7629ba56577697055cc0fcf2e/src/utils/proxy.ts#L11). + + +**Example:** + +::code-group +```ts [nitro.config.ts] +export default defineNitroConfig({ + routeRules: { + '/proxy': { proxy: "/foo" }, + '/stream/**': { proxy: { to: '/api/**', streamRequest: true } } + } +}) +``` + +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + routeRules: { + '/proxy': { proxy: "/foo" }, + '/stream/**': { proxy: { to: '/api/**', streamRequest: true } } + } +}) +``` +:: + +#### ISR + +Incremental Static Regeneration semantics on supported platforms (e.g., Netlify, Vercel). Platform presets map this to native rules/headers where available. +On platforms without native support, behavior may fall back to HTTP cache headers. + + +::code-group +```ts [nitro.config.ts] +export default defineNitroConfig({ + routeRules: { + '/docs/**': { isr: 60 }, + } +}) +``` + +```ts [nuxt.config.ts] +export default defineNitroConfig({ + routeRules: { + '/docs/**': { isr: 60 }, + } +}) +``` +:: + +#### Shortcuts + +##### Cors + +Adds permissive CORS headers. You can override or extend with `headers`. + +##### SWR + +Shortcut for `cache: { swr: true, maxAge?: number }`. Prefer `isr` on platforms with native support. + +##### Static + +Legacy alias primarily for older platform integrations. Prefer `isr` going forward. + diff --git a/docs/3.config/0.index.md b/docs/3.config/0.index.md index 67a9541ca1..647e38028f 100644 --- a/docs/3.config/0.index.md +++ b/docs/3.config/0.index.md @@ -363,6 +363,11 @@ export default defineNitroErrorHandler((error, event) => { Route options. It is a map from route pattern (following [radix3](https://github.com/unjs/rou3/tree/radix3#route-matcher)) to route options. +How matching and precedence work: +- Nitro matches the incoming path against all patterns and deep-merges every matching rule. +- More specific matches override less specific ones. For example, `/blog/post` overrides `/blog/**`, which overrides `/**`. +- The match is performed against the path only (without the query string) and without the configured `app.baseURL`. + When `cache` option is set, handlers matching pattern will be automatically wrapped with `defineCachedEventHandler`. See the [Cache API](/guide/cache) for all available cache options. @@ -371,6 +376,17 @@ See the [Cache API](/guide/cache) for all available cache options. `swr: true|number` is shortcut for `cache: { swr: true, maxAge: number }` :: +Available keys (summary): +- `cache`: CachedEventHandlerOptions | false — server-side caching (see Cache guide) +- `headers`: Record — set response headers +- `redirect`: string | { to; statusCode? } — server redirect; wildcard `/**` tail can be appended to destination; query params are preserved when the destination is not a wildcard pattern +- `prerender`: boolean — add exact routes to prerender queue at build; `false` explicitly disables +- `proxy`: string | { to } & ProxyOptions — proxy requests; wildcard `/**` tail can be appended to destination; query params are preserved when the destination is not a wildcard pattern +- `isr`: number | boolean | object — ISR/Revalidation on supported platforms +- `cors`: boolean — shortcut to add permissive CORS headers +- `swr`: boolean | number — legacy shortcut for `cache: { swr: true, maxAge? }` +- `static`: boolean | number — legacy alias; prefer `isr` + **Example:** ```js diff --git a/src/types/route-rules.ts b/src/types/route-rules.ts index 50771724b6..ce379ffde6 100644 --- a/src/types/route-rules.ts +++ b/src/types/route-rules.ts @@ -1,23 +1,156 @@ -import type { ProxyOptions, RouterMethod } from "h3"; +import type { ProxyOptions } from "h3"; import type { ExcludeFunctions, IntRange } from "./_utils"; import type { CachedEventHandlerOptions } from "./runtime"; +/** + * Valid HTTP status code range. + */ export type HTTPStatusCode = IntRange<100, 600>; +/** + * Route rule options that can be applied to matching route patterns. + * + * These options are resolved and merged for every incoming request using radix3 + * pattern matching (against the path portion without the configured app.baseURL). + * Some options are shortcuts and will be normalized into other properties + * (see {@link NitroRouteRules}). + * + * @see https://nitro.build/guide/routing#route-rules + */ export interface NitroRouteConfig { + /** + * Server-side response caching controls. + * + * - When set to an object, matching handlers are wrapped with + * `defineCachedEventHandler` using the provided options. + * - When set to `false`, server-side caching is disabled for matching routes. + * + * @remarks + * The {@link NitroRouteConfig.swr | swr} shortcut below is equivalent to + * `cache: { swr: true, maxAge?: number }`. + * + * @see https://nitro.build/guide/cache + */ cache?: ExcludeFunctions | false; + + /** + * Response headers to set for matching routes. + * + * @example + * ```ts + * headers: { + * 'cache-control': 's-maxage=600, stale-while-revalidate=86400' + * } + * ``` + */ headers?: Record; + + /** + * Server-side redirect for matching routes. + * + * You can specify: + * - A string destination (defaults to status code 307), or + * - An object with `to` and an optional `statusCode`. + * + * Wildcard behavior: + * - When the rule key ends with `/**`, the matched path (minus the base) will be appended to the `to` if it also ends with `/**`. + * - Query parameters from the incoming request are preserved when `to` is not a wildcard pattern. + * + * @example + * ```ts + * redirect: '/new-page' // 307 by default + * // or + * redirect: { to: '/new-page/**', statusCode: 301 } + * ``` + */ redirect?: string | { to: string; statusCode?: HTTPStatusCode }; + + /** + * Include this route in the prerendering queue at build time. + * + * @remarks + * - Only exact paths (no wildcards) are collected automatically into the + * prerender list. + * - Wildcard rules still apply at runtime but are not auto-added to the + * prerender queue. + * - Set to `false` on a matching rule to explicitly disable prerendering for + * that route. + * + * @see https://nitro.build/config#prerender + */ prerender?: boolean; + + /** + * Forward matching requests to another origin or internal endpoint. + * + * You can specify: + * - A string destination, or + * - An object with `to` and any additional `h3` ProxyOptions (e.g. headers, changeOrigin, etc.). + * + * Wildcard behavior: + * - When the rule key ends with `/**`, the matched path (minus the base) will be appended to `to` if it also ends with `/**`. + * - Query parameters from the incoming request are preserved when `to` is not a wildcard pattern. + * + * @see h3 ProxyOptions: https://github.com/h3js/h3/blob/ec77d6bc148e4ff7629ba56577697055cc0fcf2e/src/utils/proxy.ts#L11 + */ proxy?: string | ({ to: string } & ProxyOptions); + + /** + * Incremental Static Regeneration (ISR) / Stale-While-Revalidate semantics on supported platforms. + * + * - `number`: revalidation time in seconds. + * - `true`: never expires until the next deployment. + * - `false`: disable ISR for this route. + * + * Platform notes: + * - Platform presets (e.g., Vercel/Netlify) map this option to native rules or headers as appropriate. + * - On platforms without native support, behavior may fall back to HTTP cache headers. + */ isr?: number /* expiration */ | boolean | VercelISRConfig; - // Shortcuts + //_________________________________Shortcuts_________________________________ + + /** + * Shortcut to add permissive CORS headers. + * + * Adds defaults: + * - `access-control-allow-origin: "*"` + * - `access-control-allow-methods: "*"` + * - `access-control-allow-headers: "*"` + * - `access-control-max-age: "0"` + * + * You can override or extend with an explicit {@link NitroRouteConfig.headers | headers} rule. + */ cors?: boolean; + /** + * Shortcut for server cache SWR behavior. + * + * - `true`: enable SWR with default TTL (no `maxAge` set). + * - `number`: shorthand for `cache: { swr: true, maxAge: }`. + * + * Legacy note: + * - On platforms with native ISR (e.g., Vercel/Netlify), prefer `isr` for full platform integration. + */ swr?: boolean | number; + /** + * Legacy alias primarily used by platform presets (e.g., Vercel) historically. + * + * - In Vercel integration, `static: true` was treated similarly to `isr: false`. + * - Prefer using `isr` directly for clarity and platform support. + * + * This field is kept for backwards compatibility and may be ignored in core normalization. + */ static?: boolean | number; } +/** + * Normalized route rules that Nitro uses at runtime after resolving shortcuts. + * + * Differences from NitroRouteConfig: + * - `redirect` is always an object `{ to, statusCode }`. + * - `proxy` is always an object `{ to, ...ProxyOptions }`. + * - Shortcut fields (`cors`, `swr`, `static`) are omitted after normalization. + */ export interface NitroRouteRules extends Omit { redirect?: { to: string; statusCode: HTTPStatusCode };