Next.js 贡献指南:为警告与错误添加文档链接(Error Links)完整实践
本文基于 Next.js 仓库的 contributing/core/adding-error-links.md 贡献文档展开,讲清楚 Next.js “错误信息 + 文档链接” 机制的设计目的、新增错误文档的标准操作流程(pnpm new-error 命令背后的 Turbo 代码生成器),以及错误文档的模板结构与命名规范。读完后,你将能够在为 Next.js 提交任何新的警告或错误信息时,正确地为它生成配套的错误文档、获得对应的文档 URL,并把链接规范地写进源码中的报错信息里。
机制设计:短信息 + 长文档分离
Next.js 内置了一套为警告(warning)和错误(error)附加帮助链接的系统,其核心思想是:
- 日志中的报错信息保持简短——控制台输出不宜过长,方便开发者快速定位问题;
- 详细的成因说明与修复步骤放到文档中——每条错误信息附带一个链接,指向该错误的完整解释文档。
按贡献文档的明确要求:“In general, all warnings and errors added should have these links attached.” 也就是说,向 Next.js 新增任何警告或错误信息时,原则上都应当为其创建对应的错误文档并附上链接,而不是把所有解释直接写进报错字符串。
这套机制在仓库中可以看到大量实际用例。例如在构建入口 packages/next/src/build/index.ts 中:
// 构建缓存缺失警告
`${Log.prefixes.warn} No build cache found. Please configure build caching for faster rebuilds. Read more: https://nextjs.org/docs/messages/no-cache`
// 构建目录不可写错误
'> Build directory is not writeable. https://nextjs.org/docs/messages/build-dir-not-writeable'
// deploymentId 配置校验
'Invalid `deploymentId` configuration: must be a string. See https://nextjs.org/docs/messages/deploymentid-not-a-string'
其他典型例子还有 packages/next/src/build/handle-externals.ts 中的 https://nextjs.org/docs/messages/import-esm-externals、packages/next/src/build/generate-build-id.ts 中的 generatebuildid-not-a-string 等。可以看到,源码中引用文档时通常采用 Read more: https://nextjs.org/docs/messages/<slug> 或 See https://nextjs.org/docs/messages/<slug> 这样的写法,slug 即错误文档的文件名(去掉 .mdx 扩展名)。
标准操作流程:pnpm new-error
贡献文档给出的完整步骤只有两步,但每一步背后都有对应的工程实现,下面逐一拆解。
第 1 步:运行 pnpm new-error
该命令是仓库根 package.json 中定义的 npm script:
"new-error": "turbo gen error"
它实际调用的是 Turbo 的代码生成器(codegen)功能。生成器定义在 turbo/generators/config.ts 中,通过 plop.setGenerator('error', ...) 注册,描述为 “Create a new error document”。运行命令后会依次提示输入 4 个字段(均有非空校验):
| 提示字段 | 说明 | 示例 |
|---|---|---|
name |
使用连字符的 URL 路径 | circular-structure |
title |
错误的展示标题 | Circular Structure |
why |
为什么会出现这个错误(会填入文档的 Why 小节) | 序列化 getInitialProps 结果时的循环引用 |
fix |
可能的修复方式(会填入文档的 Fix 小节) | 移除返回对象中的循环结构 |
从 turbo/generators/config.ts 的 actions 实现可以确认其具体行为:
actions: function (answers) {
const { name } = answers as ErrorResponse
const errorsRoot = path.join(plop.getDestBasePath(), 'errors')
return [
{
// 基于模板生成 errors/<name>.mdx
type: 'add',
path: path.join(errorsRoot, `{{ toFileName name }}.mdx`),
templateFile: path.join(errorsRoot, `template.txt`),
},
// 在命令结束时输出该错误的文档 URL
`Url for the error: https://nextjs.org/docs/messages/${helpers.toFileName(name)}`,
]
}
也就是说,生成器做两件事:
- 基于模板创建错误文档:以
errors/目录为根,用 errors/template.txt 作为模板,生成errors/<name>.mdx文件(文件名经toFileName处理,保证是连字符风格); - 在命令结尾打印文档 URL:输出形如
Url for the error: https://nextjs.org/docs/messages/<name>的提示。
贡献文档也提到该命令会“create the error document and update the manifest automatically”,即由工具负责文档与清单的自动化维护,开发者无需手工登记。
第 2 步:把生成的 URL 写进你的错误信息
命令结束时打印出的 URL,就是要附加到源码报错信息中的链接。按照仓库中已有用例的惯例,将其以 Read more: / Learn more: / See 前缀拼接在简短报错文案之后即可。
错误文档模板结构
所有错误文档都从同一份模板 errors/template.txt 生成,其结构如下:
---
title: {{title}}
---
## Why This Error Occurred
<!-- Explain why the error occurred. Ensure the description makes it clear why the warning/error exists -->
{{why}}
## Possible Ways to Fix It
<!-- Explain how to fix the warning/error, potentially by providing alternative approaches. Ensure this section is actionable by users -->
{{fix}}
## Useful Links
<!-- Add links to relevant documentation -->
模板要求每个错误文档包含三块内容:
- frontmatter 中的
title:错误标题(如Circular structure in getInitialProps result); - Why This Error Occurred:解释该警告/错误为什么存在,让读者理解其成因;
- Possible Ways to Fix It:给出可操作的修复方式,最好提供替代方案;
- Useful Links:补充相关文档链接。
以 errors/circular-structure.mdx 为例,它完整遵循了模板结构:Why 部分解释了 getInitialProps 的结果通过 JSON.stringify 序列化发送给客户端用于水合,而带循环结构的对象无法被序列化;Fix 部分指出需要移除循环结构,并给出了“不要直接传 req 实例,而是挑选其中需要的字段(如相关 headers)”这种具体可操作的建议。这正是贡献文档所要求的“让 Fix 部分对用户可执行(actionable)”的体现。
命名与 URL 对应关系
从生成器实现和仓库中 errors/ 目录的现状可以归纳出命名规范:
- 错误文档统一放在仓库根目录的
errors/下,文件名为小写连字符风格的 slug 加.mdx扩展名,例如circular-structure.mdx、invalid-page-config.mdx; - 文档 URL 由 slug 直接拼出:
https://nextjs.org/docs/messages/<slug>; - 源码中引用时直接写完整 URL,slug 与文件名一一对应,例如
errors/no-cache.mdx对应https://nextjs.org/docs/messages/no-cache(构建警告中引用处见 packages/next/src/build/index.ts 第 639 行附近)。
小结
为 Next.js 新增警告或错误的完整工作流可以概括为:
- 运行
pnpm new-error,按提示填写name(连字符 slug)、title、why、fix四个字段; - 工具自动基于 errors/template.txt 生成
errors/<slug>.mdx,并在命令结尾输出该错误的文档 URL; - 完善文档中
Why This Error Occurred、Possible Ways to Fix It、Useful Links三个小节的内容,确保成因解释清晰、修复建议可操作; - 在源码中抛出该警告/错误的位置,将生成的
https://nextjs.org/docs/messages/<slug>链接按Read more:/Learn more:等惯例附加到简短报错文案之后。
相关仓库路径一览:贡献文档 contributing/core/adding-error-links.md、命令定义 package.json、生成器实现 turbo/generators/config.ts、文档模板 errors/template.txt、文档目录 errors/。
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 StartedRust0622
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