LESSON 4.5 / MODERN FRONTEND

Next.js:React 之上的生产级框架

React 管组件,Next.js 进一步管理路由、服务端渲染、数据获取、SEO 与上线所需的工程约定。

预计阅读15–20 分钟
完成结果能解释一个 Next.js 页面从文件结构到浏览器显示的过程。
本课目标
  • 能解释一个 Next.js 页面从文件结构到浏览器显示的过程。
  • 文件系统路由、布局与页面边界
  • 创建首页和详情页,添加布局、内部链接、页面标题,并检查直接访问和刷新。
开始之前
  • 完成 4.4「数据、状态与 URL 驱动界面」
01

FOUNDATION

必须理解

React 管组件,Next.js 进一步管理路由、服务端渲染、数据获取、SEO 与上线所需的工程约定。

Next.js 是 React 框架,提供路由、服务端渲染、数据获取、接口和生产构建约定。它让页面组件进入完整应用结构,但也要求理解哪些代码运行在服务器、哪些运行在浏览器。

先建立整体直觉

React 像房间内的家具系统,Next.js 像包含楼层、走廊、门牌、前台和设备间的整栋建筑规则。

贯穿本课的实际场景

任务应用的 app/page.tsx 是首页,app/tasks/[id]/page.tsx 是详情页,布局提供导航;数据读取默认在服务器,交互表单才进入客户端。

概念 1

文件系统路由、布局与页面边界

先用白话理解

在 App Router 里,文件夹和 page.tsx 会直接组成 URL,layout.tsx 可以包住一组页面。写成 [id] 的动态文件夹,则会把地址里的那一段交给页面使用。

基础概念

Next.js App Router 使用文件系统约定定义页面:`page.tsx` 提供路由内容,`layout.tsx` 包住一组页面,方括号目录表示从 URL 读取的动态片段。

进一步理解

路由段与目录对应,布局可以嵌套并在子页面切换时保留公共结构。`loading`、`error`、`not-found` 等约定文件负责相应边界状态。

动态路由 `[id]` 只说明地址形状,不证明 id 有效。页面仍需查询数据,并在不存在或无权限时返回正确结果。

放进实际场景

`app/tasks/[id]/page.tsx` 接收地址 `/tasks/42` 中的 id,再读取任务 42;公共导航放在上层 layout。

容易混淆的地方

文件系统路由不是把文件内容直接公开,访问者不能任意读取源码;框架根据约定执行组件并生成响应。

这一小节记住:目录定义地址结构,页面处理当前段,布局承载共享界面。

概念 2

服务端组件与客户端组件

先用白话理解

服务端组件先在服务器上生成结果,适合读数据和输出内容;需要点击事件、状态或浏览器 API 的部分才加 use client。客户端边界越小,页面通常越轻。

基础概念

App Router 中页面和布局默认是服务端组件;需要状态、事件处理或浏览器专用 API 时,才在客户端边界入口使用 `use client`。

进一步理解

服务端组件可在可信环境读取数据和秘密,并减少发送给浏览器的 JavaScript。客户端组件负责点击、输入、localStorage 等交互。

`use client` 会建立模块边界,该文件导入的客户端代码进入浏览器依赖图。服务端可把可序列化数据传给客户端,但秘密不能作为 props 送出。

放进实际场景

任务详情在服务端读取记录并输出标题,只有切换完成状态的按钮是小型客户端组件,通过事件提交变化。

容易混淆的地方

客户端组件也可能参与服务端预渲染,它不是“只在浏览器生成”;关键区别是其代码和交互能力会进入客户端。

这一小节记住:默认把读取与静态展示留在服务端,把客户端边界缩到真正交互处。

概念 3

预渲染、动态渲染、元数据与首屏体验

先用白话理解

有些页面可以提前生成,有些必须等用户请求时再读数据。metadata 管浏览器标题和分享信息,页面里的 h1 仍然要自己写,二者解决的不是一件事。

基础概念

预渲染是在用户请求前或请求过程中生成可发送的 HTML;静态内容可提前准备,动态内容需根据请求、身份或实时数据决定。元数据描述页面给浏览器、搜索和分享平台的信息。

进一步理解

构建时生成适合公开且变化少的内容,请求时渲染适合个性化与实时数据。缓存会改变再次访问的计算时机,因此必须理解数据新鲜度。

title 与 description 帮助识别页面,但不能代替正文的 h1、语义结构和真实内容。首屏体验还受数据等待、流式响应与客户端脚本大小影响。

放进实际场景

公开课程页可预生成;用户自己的任务页必须按身份读取。两者都设置准确标题,并为加载过程提供可理解反馈。

容易混淆的地方

动态不等于一定更慢,静态也不等于永远正确;选择取决于数据是否依赖请求以及允许多旧。

这一小节记住:按数据时效和身份需求选择渲染时机,再用元数据准确描述页面。

文件系统动态路由
运行前先确认
  • 文件位于 `app/tasks/[id]/page.tsx`。
  • 当前 Next.js 版本的 params 是异步值,因此页面函数使用 async。
export default async function TaskPage({
  params,
}: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  return <h1>任务 {id}</h1>;
}
这段代码在做什么

位于 app/tasks/[id]/page.tsx 时,URL 中的 id 会通过 params 交给页面。

  1. 类型说明 params 最终提供字符串 id。
  2. await params 取得当前动态路由片段,而不是从浏览器全局对象读取。
  3. 示例只展示参数;真实页面还要查询资源并处理不存在与无权限。
你应该观察到

访问 `/tasks/42` 时页面显示“任务 42”;换成其他地址片段会显示对应值,未知 id 的业务校验仍需另行实现。

02

AI COLLABORATION

AI 如何参与

让 AI 说明一个组件为什么必须在客户端运行;默认把纯展示和数据读取留在服务端。

推荐协作顺序

  1. 1

    先让 AI 根据 URL 需求画出 app 目录,不生成页面细节。

  2. 2

    逐个组件询问它是否真的需要事件、状态或浏览器 API。

  3. 3

    把客户端边界压到最小后,再验证直接访问、刷新和 404。

可直接使用的 Prompt
请为 Next.js App Router 的任务应用设计最小路由:/、/tasks/[id]、/about。先画文件树,标出服务端组件和必须使用 use client 的最小交互组件,并解释每个边界原因。不要给所有文件加 use client。
应该得到什么

路由与文件结构一一对应,大部分页面保持服务端,只有表单和交互控件作为小型客户端组件。

人工检查清单

  • 确认动态参数正确读取,内部导航使用 Link,刷新详情页仍能工作,metadata 不含虚构数据。
  • 要求 AI 为每个组件说明必须在哪个环境运行的具体理由,并指出传输边界。
  • 直接访问、刷新动态路由并检查页面源码与交互,验证路由和渲染时机符合预期。
03

COMMON TRAPS

常见误区

错误不是需要隐藏的失败,而是帮助你看清系统边界的证据。下面三类问题在 AI 辅助学习中最常出现。

误区 1

每个文件都加 use client

你会看到
为了消除一个报错,把整个页面树都变成客户端代码。
为什么发生
给顶层文件加 use client 会把整条导入链推向客户端,增加脚本并让服务端秘密与数据读取更难管理。
怎样纠正
找到真正需要交互的最小组件,只在那条边界使用客户端指令。
误区 2

把文件夹名当成页面标题

你会看到
路由能访问,却没有独立 metadata 和清楚的页面结构。
为什么发生
把动态段当成可信数据会造成不存在资源报错或越权,URL 只能提供候选标识。
怎样纠正
文件夹决定 URL,页面内容与 metadata 仍要分别设计。
误区 3

只测试站内点击

你会看到
从首页点进详情正常,直接刷新详情却报错。
为什么发生
只设置 metadata 而正文缺少清楚标题和结构,搜索摘要可能存在,真实用户与辅助技术仍难理解。
怎样纠正
每个路由都要测试直接访问、刷新和不存在参数。
04

HANDS-ON

动手任务

创建首页和详情页,添加布局、内部链接、页面标题,并检查直接访问和刷新。

准备条件
  • 完成 4.4「数据、状态与 URL 驱动界面」

跟着做

  1. 01

    创建首页、关于页和共享布局。

  2. 02

    加入任务详情动态路由并使用示例参数。

  3. 03

    使用 Link 在页面之间导航。

  4. 04

    把 TaskForm 单独标记为客户端组件。

  5. 05

    为三类页面设置标题,测试直接访问、刷新和不存在 ID。

完成标志

能解释一个 Next.js 页面从文件结构到浏览器显示的过程。

加餐挑战

为不存在的任务返回专用 404,并为详情页生成包含任务标题的 metadata。

离开本课前,自问四件事

  • page、layout、动态路由段分别怎样组成 URL 与页面?
  • 哪些能力必须使用客户端组件,哪些适合留在服务端?
  • use client 为什么应放在尽量小而明确的边界?
  • 静态与动态渲染应根据哪些数据条件选择?
完成本课了吗?

确认完成后,会同步更新学习中心的课程学习进度。