Skip to content

Nuxt路由规则与混合渲染策略重构

这次整理的对象主要来自下面这些本地素材:

  • 11Vue学习/Nuxt4/核心概念/4Rendering-modes.md
  • 11Vue学习/Nuxt4/note/nuxt-lifecycle.md
  • 11Vue学习/组件化思维/Nuxt数据获取与渲染模式重构.md
  • 11Vue学习/组件化思维/Nuxt中间件与插件注入边界重构.md

和前面的案例一样,这一轮不直接修改任何独立项目,而是把其中最值得复用的“路由规则、混合渲染、缓存策略和部署侧响应方式”思路整理成一篇案例文档。

这类场景最容易被低估的地方,不是 routeRules 配置怎么写,而是“页面为什么应该使用这类响应策略”:

  • 某个页面到底应该 SSR、CSR、预渲染,还是混合渲染
  • 哪些页面适合 swr / isr
  • 哪些页面根本不应该进入服务端渲染路径
  • 路由规则应该服务于页面价值,还是只是部署技巧
  • 页面数据策略和响应缓存策略是否已经打通

如果这些边界不先理清,项目后面就很容易出现几个典型问题:

  • 全站统一一种渲染模式,结果内容页和后台页都不合适
  • 页面已经能跑,但缓存命中、更新时机和用户体验都说不清
  • ssr: falseprerenderswrisr 被当成零散配置项,而不是页面级决策
  • 页面层选了某种数据获取方式,部署层又给了相反的响应策略

这类场景真正的复杂度中心

Nuxt 路由规则与混合渲染场景里,最容易被忽略的复杂度中心,不是配置项数量,而是“页面价值如何映射到响应策略”。

从当前素材可以看到几个很关键的方向:

  • 某些页面更关心首屏 HTML 与可索引性
  • 某些页面更关心交互性和浏览器能力
  • 某些页面内容稳定,适合预生成或缓存复用
  • 某些页面更新频繁,但又值得保留服务端响应能力

如果这些差异不先抽象出来,项目很快会出现:

  • 内容页、登录页、后台页用同一套渲染策略
  • 运维层配置缓存,前端层却不知道为什么要这么配
  • 页面已经拆分出首屏数据与交互数据,但路由规则仍然混乱
  • 团队讨论页面性能问题时,只有“快不快”,没有“为什么这样渲染”

所以这类重构的重点,不是先记住所有配置项,而是先把“页面价值 -> 渲染策略 -> 路由规则”这条链路收口清楚。

推荐的重构边界

更适合长期维护的结构,通常会把这类场景拆成下面几层:

  • 页面价值层:负责定义页面是内容优先、交互优先还是后台工作台
  • 渲染策略层:负责选择 SSR、CSR、预渲染或混合渲染
  • 路由规则层:负责把页面策略映射为 routeRules
  • 页面数据层:负责页面首屏数据与交互数据分层
  • 部署响应层:负责缓存与边缘策略最终如何落地

如果换成更具体的职责,大概可以这样理解:

  • PageRenderingPolicy:负责页面类别与目标
  • defineRouteRulesMap():负责集中声明 routeRules
  • usePageData():负责页面数据获取方式
  • pages/**:只负责页面内容与交互装配
  • 部署平台:负责消费最终生成的路由规则与缓存策略

这里最重要的一条原则是:

  • 先决定页面价值,再决定响应方式
  • 路由规则不是部署层孤立配置,而是页面决策的延伸
  • 数据流与缓存流必须站在同一套页面语义上

routeRules 解决的是页面级响应策略,不是单纯部署技巧

很多项目第一次接触 routeRules 时,会把它理解成“运维或部署阶段的配置补丁”。这会导致前端团队几乎不参与策略设计。

更稳的理解应该是:routeRules 其实是在为每类页面声明“服务器应该如何响应这个 URL”。

它真正适合承载的是:

  • 哪些路由要关闭 SSR
  • 哪些路由适合 swr
  • 哪些路由适合 isr
  • 哪些路由适合构建期 prerender
  • 哪些路由需要额外的 appMiddleware 或响应头策略
ts
export const routeRules = {
  '/': { swr: 300 },
  '/articles/**': { isr: 3600 },
  '/dashboard/**': { ssr: false },
  '/about': { prerender: true },
}

这样团队讨论页面策略时,问题就会从“配不配缓存”变成:

  • 这个页面值不值得缓存
  • 这个页面允许多久的数据滞后
  • 这个页面是不是根本不该服务端渲染

先分清内容页、交互页、后台页,再谈渲染模式

真正稳定的渲染策略,往往不是按技术分类,而是按页面价值分类。

更稳的划分方式通常是:

内容优先页

例如文章页、活动页、专题页。

这类页面通常更适合:

  • SSR
  • 预渲染
  • swr / isr

因为它们更关心:

  • 首屏可见内容
  • SEO 与索引效率
  • 响应复用与缓存命中

交互优先页

例如个人中心、复杂编辑区、浏览器能力强依赖页面。

这类页面通常更适合:

  • CSR
  • 局部客户端增强
  • ClientOnly、异步模块结合使用

后台工作台页

例如仪表盘、管理台、运营后台。

这类页面往往更适合:

  • 路由级 ssr: false
  • 明确的 SPA loading 模板
  • 更注重导航体验与客户端缓存

如果这层页面价值分类不先做,渲染模式就很容易退化成“大家都这么配”的习惯配置。

swr / isr / prerender 要和内容更新节奏对齐

很多团队在用这些策略时,只看到名字,却没有把它们放回“内容更新频率”的语境里。

更稳的理解可以很简单:

  • prerender:适合构建期就能稳定生成、更新频率低的页面
  • swr:适合允许短时间过期、但又希望服务端快速复用响应的页面
  • isr:适合内容持续存在且希望 CDN 层复用结果的页面

如果内容更新节奏和响应策略不匹配,就会出现:

  • 页面已经更新,用户长时间看到旧内容
  • 页面本不值得实时生成,却持续消耗服务端算力
  • 页面本该静态生成,却在请求时重复做服务端工作

所以 swr / isr / prerender 最终都不该只是技术选型,而应该是“内容时效要求”的表达。

页面数据策略和响应策略必须一起设计

这也是很多项目里最容易断裂的一层:

  • 页面层已经把首屏数据、客户端交互数据分开
  • 但路由规则仍然没有随页面职责变化一起调整

结果就是:

  • 页面内部逻辑已经偏向客户端交互
  • 外层却还在强制保留重 SSR 路径
  • 或者页面明明是内容页,内部数据流却写得像纯客户端工作台

更稳的方式是:

  • 首屏必须内容,优先匹配 SSR / 预渲染 / 缓存型策略
  • 交互后才需要的数据,优先留给客户端获取
  • 后台工作台页,把核心体验目标转成导航与交互流畅性

也就是说,页面数据策略和响应策略必须站在同一套页面语义上,而不是各自独立演化。

ssr: false 不只是关掉 SSR,而是切换页面责任模型

很多人把 ssr: false 理解成一个性能开关,但它真正改变的,是页面责任模型。

一旦某一类页面使用 ssr: false,就意味着:

  • 首屏 HTML 不再承担主要内容表达责任
  • 客户端应用加载体验变得更重要
  • spa-loading-template 这类占位策略必须被认真设计
  • 页面 SEO 与首屏直出能力通常不再是重点目标

所以 ssr: false 更像一种页面架构选择,而不是“先关掉再看”的快捷优化。

混合渲染的重点不是“多”,而是“按页面价值分配”

Nuxt 混合渲染真正有价值的地方,不是让你一次性用上所有模式,而是允许不同页面各自使用最合适的策略。

更稳的目标应该是:

  • 内容页尽量稳定复用响应
  • 工作台页尽量减少不必要的 SSR 负担
  • 活动页与专题页尽量在构建期或缓存期完成生成
  • 客户端增强模块和页面整体响应策略互相协调

如果混合渲染只是“这里配一个 swr,那里关个 SSR”,而没有页面价值模型做支撑,项目迟早会再次失去一致性。

更适合现代 Nuxt 的组织方式

如果把这类“路由规则散落在配置和讨论里”的结构迁到更稳定的项目组织方式,更推荐的边界通常是:

  • docs/rendering-policy.md 或内部策略说明
  • nuxt.config.ts 内集中维护 routeRules
  • composables/page/usePageData.ts
  • pages/**/*.vue

在这套结构里:

  • 页面价值模型先被定义
  • 路由规则只做策略映射
  • 页面数据层和响应策略层保持一致
  • 页面组件只负责内容与交互装配

这和前面几个案例的方法是一致的:

  • 先找到复杂度中心
  • 先稳定页面分类与策略边界
  • 再把配置和实现落到对应层级
  • 最后再优化具体页面体验

这类项目最值得先检查的 6 个问题

以后再遇到类似“Nuxt 页面很多、内容页和后台页混在一起”的项目,可以先检查这几个问题:

  1. 页面是否已经按价值分成内容页、交互页、后台页
  2. routeRules 是否表达了页面级策略,而不是零散配置
  3. swr / isr / prerender 是否和内容更新节奏一致
  4. 页面数据流与响应缓存流是否站在同一套语义上
  5. ssr: false 是否被当作页面责任模型切换来使用
  6. 混合渲染是否真正服务于页面差异,而不是配置堆叠

如果这 6 个问题答不清楚,就说明当前项目的渲染与响应策略还没有真正收口。

这篇案例最后沉淀出的核心方法

这轮最重要的不是再多配几条 routeRules,而是沉淀出一条可复用的 Nuxt 渲染策略重构思路:

  • 先按页面价值分类
  • 再把页面价值映射成响应策略
  • 再让数据流和缓存流围绕同一套页面语义协同
  • 最后让 routeRules 成为页面决策的稳定表达

这样以后面对内容站、活动页、管理后台、混合型站点这些场景时,Nuxt 的渲染模式和路由规则都能落在同一套稳定框架里,而不会继续演变成零散配置集合。

共 20 个模块,1301 篇 Markdown 文档。