N21第 1 / 1 课时未开始内容版本 1.0.0 · 核验于 2026-10-26

测试与故障排查

测试与故障排查 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。

学习目标

「dev 里好好的,build 就报错」是 App Router 最高频的事故。本课建立三层防线:核心路由的冒烟检查、写入与恢复的回环验证、以及一套「先复现再修复」的排查流程——每个修复都留下可复现的证据。

问题场景

你改了一行代码,dev 一切正常,npm run build 却炸了:某个页面在构建期预渲染时去连数据库,而构建环境根本没有库文件。事后你修好了,但下次换个姿势又踩——因为没有测试兜底,也没留下「当时是怎么坏的」的记录。

核心解释

先理解 dev 与 build 的差异:next dev 按需渲染、报错宽松;next build 会把所有没有动态信号的页面在构建环境里预渲染——这时执行的代码一旦访问数据库、读环境变量,都可能当场失败。排查构建问题的第一问永远是:「这个页面为什么会在构建期执行?」

# 三个检查各跑一遍,差异就是线索
npm run lint
npm run typecheck
npm run build

核心路由冒烟:服务起来后挨个请求,断言状态码:

// tests/smoke.mjs(与工程里 scripts/e2e-core.mjs 同思路)
const BASE = "http://localhost:3000";
const checks = [
  ["/", 200],
  ["/courses", 200],
  ["/courses/n07-server-data-access", 200],
  ["/courses/not-exist", 404],
  ["/api/notes?page=1", 200],
];

for (const [path, expected] of checks) {
  const res = await fetch(BASE + path);
  const ok = res.status === expected;
  console.log(ok ? "PASS" : "FAIL", path, res.status, "期望", expected);
  if (!ok) process.exitCode = 1;
}

写入与恢复回环:冒烟只证明「读没问题」,写链路要单独验证——建一条测试笔记 → 读回字段一致 → 导出备份 → 重建空库 → 导入恢复 → 再读回。任何一步失败都能精确定位是写入、备份还是恢复的问题。

故障要留证据:修复一个 bug 的交付物有三样——复现步骤(最小命令序列)、失败时的报错原文、修复后的验证输出。存进 data/ 或提交信息里,下次同类问题翻的是档案,不是记忆。

示例拆解

完整排一遍本机工程:

  1. npm run build——观察输出表:静态(○)/ 动态(ƒ)各是哪些路由;某个「该动态的页面」被标成静态,就是事故预备役。
  2. npm run test(vitest)与冒烟脚本全绿。
  3. 制造一次故障:把笔记页的 force-dynamic 删掉再 build,观察它变静态、预渲染时读库报错——记下报错原文。
  4. 加回 force-dynamic 修复,把「复现步骤 + 报错 + 修复验证」三件套存档。

关键点:测试不是追求覆盖率数字,而是把「你怕它坏的地方」固化成可自动重放的断言。个人项目优先保三处:核心路由、写操作、备份恢复。

动手任务

在本机工程里完成:

  1. 跑通 lint / typecheck / build 三连,把 build 输出的路由类型标记存档。
  2. 给核心路由写冒烟清单(含一个必须 404 的路径),接入 npm script。
  3. 完整走一次「写入 → 导出 → 重建 → 恢复 → 验证」回环,失败过就留下证据。

常见错误

  • 只信 dev 环境绿就交付:构建期预渲染、生产压缩、缓存行为只在 build/start 里暴露。
  • 测试断言内部实现:断言「调用了某函数」一重构就废;应断言可见行为(状态码、响应字段)。
  • 修完不留证据:同一个坑三个月后再踩,成本翻倍。
  • 测试数据混进真实库:冒烟脚本往正式数据里插记录;测试要用独立数据目录(REACTLAB_DATA_DIR 指到临时路径)。

检查与复盘

自查清单:

  • build 输出的路由类型逐个过目,动态页没有被误标成静态
  • 冒烟清单覆盖核心读、一个 404、一次写回环
  • 最近一次修复有复现步骤与前后输出存档

参考资料

检查题共 1 题,提交后立即显示解析
答案由服务端判定;答错的题会自动进入复习计划。
Q1单选简单

npm run dev 一切正常的项目,为什么交付前还必须跑一次 npm run build 并用产物验证?

读完这一课了?

标记完成后,工作台会安排接下来的学习。

Command Palette

Search for a command to run...