Nuxt 3 defineRouteRules 页面级路由规则详解:在组件内实现 Hybrid Rendering 配置
导读
defineRouteRules 是 Nuxt 提供的一个实验性编译期宏,它允许你在页面组件的 <script setup> 中直接声明该页面所属的路由规则(route rules),从而以“就近声明”的方式实现混合渲染(Hybrid Rendering)的按页配置。读完本文,你将掌握如何启用 experimental.inlineRouteRules、如何在页面内编写与 nuxt.config.ts 中等价的 routeRules、理解页面路径与路由规则的转换规则(含动态参数与正则的限制),并了解其底层在 pages 模块中的实现与冲突处理机制。
这是什么:页面级(inline)路由规则
在 Nuxt 中,routeRules 是一种强大的路由级配置,可对某一路径启用 prerender(预渲染)、swr、redirect、缓存头等混合渲染行为。传统上这些规则统一写在 nuxt.config.ts 的 routeRules 字段中。
而 defineRouteRules 把这个能力下沉到了页面内部——它定义的是当前页面的路由规则,编译期会依据页面文件的 _path_ 自动生成匹配的路由规则,并合并进 Nitro 的全局 route rules 中。
<script setup lang="ts">
defineRouteRules({
prerender: true,
})
</script>
<template>
<h1>Hello world!</h1>
</template>
上述代码等价于在 nuxt.config.ts 中书写:
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true },
},
})
也就是说,当执行 nuxt build 时,首页会被预渲染输出到 .output/public/index.html,并以静态文件的方式对外提供服务,而无需你在根配置中集中维护这些规则。
前置条件:必须先启用 experimental.inlineRouteRules
defineRouteRules 属于实验性功能(官方文档将其标注为 experimental),使用前必须在 nuxt.config.ts 中开启对应开关:
export default defineNuxtConfig({
experimental: {
inlineRouteRules: true,
},
})
该开关定义于 packages/schema/src/config/experimental.ts 中,并在 packages/nuxt/src/pages/module.ts 中决定两条关键执行路径:
- 当
experimental.inlineRouteRules开启时,pages 模块会通过handleRouteRules调用globRouteRulesFromPages(pages)把各页面声明的规则收集成一份Record<string, NitroRouteConfig>,随后在nitro:init钩子中调用nitro.updateConfig({ routeRules })动态合并进 Nitro 配置并执行nitro.routing.sync()同步路由; - 当开关关闭时,则会调用
removePagesRules(pages)清理掉页面对象上的 rules 字段,避免其泄露到构建产物中(packages/nuxt/src/pages/route-rules.ts)。
此外,defineRouteRules 这个标识符本身也仅在开启该实验项后才会被加入自动导入预设(routeRulesPresets),源码见 packages/nuxt/src/pages/module.ts 中的 imports:sources 钩子。
宏的签名与定位:编译期函数而非运行时 API
与 definePageMeta、defineNuxtConfig 类似,defineRouteRules 是一个编译期宏(compiler macro),并非普通的运行时函数。在 packages/nuxt/src/pages/runtime/composables.ts 中,它的运行时实现是一个空函数:
export const defineRouteRules = (rules: NitroRouteConfig): void => {}
其参数类型为 Nitro 的 NitroRouteConfig(来自 nitro/types),这意味着你在页面内可书写的规则集合与 nuxt.config.ts 中 routeRules 支持的字段完全一致(如 prerender、swr、redirect、cors、缓存与响应头配置等)。
真正的工作发生在编译期:Nuxt 会对页面文件做静态 AST 分析,提取 defineRouteRules({ ... }) 传入的字面量对象。从 packages/nuxt/src/pages/utils.ts 的提取逻辑可以看到,传给 defineRouteRules 的参数必须可序列化(isSerializable 校验),一旦包含不可序列化内容(如函数、非字面量表达式),会触发 NUXT_B4006 诊断并跳过提取。提取成功后,规则会写入路由对象的 rules 字段,供后续收集使用。这也解释了为什么 defineRouteRules 只能在页面组件(或具备路由上下文的位置)的 <script setup> 顶层使用,且参数必须是静态可分析的纯对象。
路径与规则的映射规则
规则生效范围由页面文件路径与 route config 共同决定。核心转换逻辑集中在 packages/nuxt/src/pages/route-rules.ts 的 collectRouteRulesFromPages 中:它递归遍历页面树,将「前缀 + 页面路径」交给 vueRouterToRou3(来自 unrouting 包)转换成 Nitro/rou3 的路由匹配模式,规则即绑定到该模式上。
官方文档与对应测试 packages/nuxt/test/route-rules.test.ts 共同验证了以下几类映射行为:
1. 静态路径:一一对应
规则定义在 ~/pages/foo/bar.vue,会应用到 /foo/bar 请求。
2. 动态参数:转换为通配段
规则定义在 ~/pages/foo/[id].vue,会应用到 /foo/* 请求——参数段被折叠为单段通配符。测试中的 '/foo/:id/bar' 对应转换结果即为 '/foo/*/bar'。注意这也会隐含匹配 /foo/* 下的嵌套路径。
3. 有限备选参数:逐项展开
页面通过 definePageMeta 的 path 设置了有限候选集,例如 /:locale(en|fr)/about,则会为每个候选生成一条独立规则(/en/about 与 /fr/about),测试用例也验证了 /:locale(de|fr)/account/verify 会被展开为 '/de/account/verify' 与 '/fr/account/verify' 两条规则且不产生告警。
4. 嵌套路由:前缀拼接
子路由的规则会与其父路由路径前缀拼接,例如测试中 /some 下的嵌套页面 nested/page 最终生成 '/some/nested/page'。
无法转换的路径:规则被丢弃并告警
并非所有页面路径都能被无损地转换成等价的路由规则模式。如果遇到以下难以表达的情形,该页面的规则将不会生效,Nuxt 会在构建期给出告警:
- 带正则约束的参数,如
/:id(\d+); - 参数内嵌于段中的「局部段」,如
/prefix-:id; - 可重复参数(catch-all),如
/:slug+。
此时正确的做法是在 nuxt.config.ts 的 routeRules(或 nitro.routeRules)中显式定义这些规则,而不是依赖页面内声明。
底层实现印证了这一行为:在 packages/nuxt/src/pages/route-rules.ts 中,vueRouterToRou3(path, { collapse: true }) 会返回 patterns 与 issues,一旦存在转换问题(issues 非空),该页面的规则既不会写入结果,还会触发 NUXT_B4016 诊断,提示例如 “Collapsed ... into a ** catch-all, which also matches nested paths” 这类信息。对应测试(packages/nuxt/test/route-rules.test.ts 中 'drops rules and warns when a path cannot be converted exactly')验证了 /account/:id(\\d+) 这类路径转换后得到的收集结果为空集,且告警被触发。
另外,若不同页面(如 /foo/:id 与 /foo/:slug)的规则最终折叠到同一个模式(/foo/*),后收集的规则会覆盖先前的规则,同时触发 NUXT_B4017 冲突诊断。因此,当两个动态页面需要不同的规则时,必须到 nuxt.config 的 routeRules 中用更精确的模式分别声明。
何时应改用 nuxt.config 中的 routeRules
官方文档明确给出了建议边界:如果你需要更精细的控制,例如在页面的 definePageMeta 中设置了自定义 path 或 alias,则应当直接在 nuxt.config 中设置 routeRules。
从实现细节看,这个建议是合理的——definePageMeta 本身支持的 path、alias、redirect 等能力用于影响 vue-router 层的路由记录(packages/nuxt/src/pages/runtime/composables.ts 中 PageMeta 接口声明的字段),而 inline route rules 是基于「转换后能精确表达的路径模式」来工作的。当存在自定义复杂路径、别名或正则受限参数时,集中式 routeRules 仍是覆盖面最广、控制力最强的配置方式。
从使用心智上看,两者可以这样分工:
| 场景 | 推荐写法 |
|---|---|
| 静态页面 / 规则模式能由文件路径精确表达 | 页面内 defineRouteRules |
| 少量页面需要差异化混合渲染 | 页面内 defineRouteRules |
自定义 path、alias 或正则、catch-all 参数 |
nuxt.config.ts 的 routeRules |
| 需要全局限流、跨页统一规则、复杂模式 | nuxt.config.ts 的 routeRules |
在构建中的实际效果:预渲染示例
回到开头示例,启用后执行 nuxt build,首页将按 { prerender: true } 处理,预渲染产物出现在 .output/public/index.html,后续作为静态文件直出;配合 Nuxt 的混合渲染模型,其他未声明规则或未命中 prerender 的页面仍可走 SSR/SPA 等默认链路,从而实现「一张配置、按页混合」的站点架构。更多关于 route rules 整体能力与混合渲染的概念背景,可继续阅读 hybrid rendering 指南 与 definePageMeta 文档。
小结
defineRouteRules是实验性页面级 route rules 宏,需先在nuxt.config开启experimental.inlineRouteRules;- 它的运行时实现为空,规则在编译期被静态提取(要求可序列化),随后按页面路径转换为 Nitro 路由规则并合并进构建配置,相关逻辑可追踪 packages/nuxt/src/pages/route-rules.ts 与 packages/nuxt/src/pages/module.ts;
- 静态路径一一对应、动态参数折叠为通配、有限备选路径逐项展开;正则参数、局部段参数与可重复参数无法转换,规则会被丢弃并触发构建告警,此时应回退到
nuxt.config集中定义; - 测试 packages/nuxt/test/route-rules.test.ts 完整覆盖了提取、展开、丢弃告警与覆盖冲突等全部路径转换行为,可作为理解规则边界的可执行参考。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00