博客详情
Next.js App Router:路由、渲染与数据获取入门
从 pages 迁移视角理解 App Router 的核心概念
约 4 分钟阅读
当你从 pages 目录迁移到 app 目录时,最先需要调整的不是语法细节,而是心智模型:路由如何由文件夹表达、布局如何嵌套、数据默认在哪里取。本文从工程视角整理 App Router 的常见决策点,便于在真实项目里落地。
为什么会出现 App Router
pages 路由以文件名为 URL,能力成熟,但在嵌套布局共享、服务端组件、流式渲染等方面需要额外约定。App Router 把这些能力纳入同一套路由树:layout 持久化、page 映射叶子路由、loading/error 提供边界。对团队而言,这意味着更少的「全局壳子」重复代码,以及更清晰的加载与错误策略。
与 Pages Router 的共存
Next.js 允许 app 与 pages 并存一段时间。迁移策略通常是:新功能走 app,旧页面逐步搬迁;或按业务域切分路由段。注意 URL 不能冲突,且两套目录的数据获取与 Head 管理方式不同,需要单独验证 SEO 与统计埋点。
路由与文件约定
app 下的每个文件夹是一个 segment。page.tsx 暴露为可访问路由;layout.tsx 包裹本段及子段;route.ts 暴露 HTTP 端点。动态段使用 [slug],拦截路由、并行路由属于进阶能力,可在稳定迁移后再引入。
layout 与 template 的差别
layout 在导航切换时保持状态(例如滚动位置、内部表单草稿);template 每次导航会重新挂载子树。默认优先使用 layout;当你明确需要每次进入都重置局部状态时,再考虑 template。
服务端组件与客户端组件
Server Components 是默认。它们可以直接 async,在服务端拉取数据并输出 HTML,减少浏览器端 JS 体积。只有在需要事件处理、useState、浏览器 API 或第三方仅客户端库时,才在文件顶上加 use client 或把交互拆到子组件。
组合模式
常见写法是:页面为服务端组件,内部引入若干小的 Client Component(表单、对话框、图表)。避免在根 layout 大面积标记 use client,否则容易把整个子树打包进客户端 bundle。
数据获取与缓存语义
在服务端组件中,fetch 默认会利用 Next 的缓存策略(可按路由段配置 revalidate 或动态渲染)。访问数据库时,优先在服务端完成查询,不要把密钥带进浏览器。若需要客户端轮询或乐观更新,把数据层放在 Client Component,并配合 Route Handler 或 BFF。
与外部 API 协作
对内网服务或第三方 API,注意超时、重试与错误映射;在服务端集中处理鉴权头,避免把 token 暴露给前端。对可缓存的公开内容,可结合 fetch 的 next: { revalidate } 做增量更新。
loading、Suspense 与流式渲染
loading.tsx 会在对应段展示占位 UI,并与 React Suspense 协作实现流式输出。对首屏关键路径,尽量让首包尽快可见;次要模块可拆到独立 Suspense 边界,减少「全页白屏」时间。
错误与兜底
error.tsx 提供错误边界,可记录日志并给用户可恢复路径。对动态路由,若数据源偶发失败,边界内降级 UI 往往比整页 500 更可接受。
迁移 Checklist
- 列出所有路由与布局嵌套关系,标出共享壳与仅页面级 UI。
- 标注哪些页面必须客户端交互,拆出最小
use client子树。 - 核对
metadata/generateMetadata与旧站 SEO 字段。 - 压测关键接口与 TTFB,确认服务端数据路径无 N+1。
- 预发环境跑一遍
next build,检查动态/静态划分是否符合预期。
小结
App Router 的价值在于把路由结构、渲染边界与数据路径绑在同一棵树上。先想清楚「默认服务端、局部客户端」的分工,再谈具体语法,迁移会顺很多。后续若你使用国际化、并行路由或 Server Actions,可在稳定主干后再逐项引入。