Vercel的AGENTS.md技能指南教授AI助手70条React最佳实践
深入探讨 Vercel 的 react-best-practices agent 功能,展示其如何将 70 条经过生产环境验证的 React 规则直接嵌入到 AI 生成的代码中。
平台团队的一位同事在内部 Slack 频道里分享了一个链接,却未作任何解释——只有原始网址和一个耸肩表情符号。该链接指向 vercel-labs/agent-skills 仓库中的 react-best-practices 模块。大家原本以为这又会是一篇为迎合人工智能潮流而重新包装的“React 性能技巧”清单,但实际并非如此。这是一份涵盖 8 个类别、共 70 条规则的准则,Vercel 表示这些规则是基于十多年来观察生产环境中的 React 和 Next.js 应用程序反复出现的故障总结而成的。关键在于,它首先是为人工智能编码助手设计的,人类开发者则作为次要使用对象。
这种框架设计正是让该方案如此出色的核心所在,在深入研究具体规则内容之前,值得先花时间了解它。
仓库中实际包含的内容
安装该技能只需一条命令:
npx skills add vercel-labs/agent-skills
在后台,这条命令会编译成一个 AGENTS.md 文件——这种格式正逐渐成为向编程智能体提供结构化项目上下文的标准(Claude Code、Cursor、Codex 和 OpenCode 等工具都会查找此文件)。一旦该文件生成,智能体在编写或审查代码时就能参考相应的规则手册,而无需完全依赖其训练数据中偶然收集到的各种 React 教程内容。
这70条规则被分为八类,每类都带有从“CRITICAL”到“LOW”的优先级标签。显然,被标记为“CRITICAL”的两类正是Vercel团队所指出的最容易引发实际问题的根源:会导致级联效应的顺序异步操作,以及未受控制的代码包体积增长。属于级联效应类别的一条典型规则表述如下:
// Flagged: sequential awaits create a waterfall
async function getThreadPage(threadId) {
const thread = await getThread(threadId)
const author = await getAuthor(thread.authorId)
const replies = await getReplies(threadId)
return { thread, author, replies }
}
// Preferred: parallelize independent fetches
async function getThreadPage(threadId) {
const [thread, replies] = await Promise.all([
getThread(threadId),
getReplies(threadId),
])
const author = await getAuthor(thread.authorId)
return { thread, author, replies }
}
如果你有过使用React进行开发的经验,这些内容其实并不算什么创新。真正有趣的是,这些规则现在以一种机器能够解析并在整个代码库中统一应用的形式存在——即便是在凌晨2点,针对那些无人仔细审查的拉取请求,也能做到这一点,而且不会因为截止日期临近而出现疲劳或走捷径的情况。
为何这与代码检查工具不同
人们首先会疑惑这是否只是换了个名字的 ESLint。从某些方面来看确实如此——但它的运作机制使其与众不同。代码生成完成后,lint 工具才会标记问题;而这种方法的目的是在代码仍在生成时就对其产生影响,在问题被敲入键盘之前就发现它。如果某个 AI 助手负责某次 pull request 中 30% 到 60% 的代码差异(不同团队成员给出的比例差异很大),那么将规则直接嵌入生成过程,与事后纠错相比,其实是一种根本不同的干预方式。
还有一类指导内容是代码检查工具根本无法妥善表达的:架构层面的判断。像“避免使用瀑布式结构”这样的规则,只要给予足够的自定义配置以及对误报的容忍度,代码检查工具至少可以大致实现。但诸如“由于该组件没有交互行为,且围绕它划定的客户端边界看起来很随意,因此它或许应该变成服务器组件”这类判断,则需要基于意图和结构的实际推理——这正是需要人工介入决策的领域,而非通过模式匹配来强制执行的。
怀疑情绪的滋生之处
直接点明那些令人不适的问题是必要的。由构建该框架的同一家公司制定的规则,加之其托管平台恰好会奖励某些特定的性能表现模式,这类文档本质上就不可能是中立的。关于包大小的一些关键级指导建议,与那些能让 Vercel 自身的分析仪表板和边缘缓存设置显得更出色的性能模式过于吻合。这种重合并不一定意味着这些建议就是错误的。无论由谁来提供应用服务,避免使用异步流水线都是合理的工程实践。不过,我们应当记住,供应商推荐的“最佳实践”从来都不是纯粹的技术性内容——在工程建议的背后,总隐藏着微妙的营销意图。
第二个担忧更具结构性:一旦70条规则增加到200条,或者来自不同供应商的技能开始被放入同一个AGENTS.md文件中且彼此矛盾,将会发生什么?目前由于只有一个代码库以及全新的设计理念,一切看起来都很整洁,也易于理解。但18个月后,不难想象每个框架、每家托管服务提供商以及每个设计系统都会希望自己的技能被安装进去。到那时,你的智能体可能要同时处理一堆相互冲突的规则手册,而且很可能没有明显的方法来判断哪一套规则应该被优先采用。
在真实代码库中进行测试
出于好奇而非预期,我们将该工具应用于一个中等规模的内部控制面板,想看看它能发现什么问题。结果发现那些“严重”和“高优先级”的问题其实都很平常:几处本可以并行执行的连续await调用,几个并无必要作为客户端组件的元素,以及一个颇为尴尬的情况——仅仅为了格式化一个数值就引入了整个日期处理库。对于那些曾经认真分析过React代码库性能的人来说,这些根本不算什么意外。真正令人印象深刻的是速度——该工具仅需大约四分钟就能定位并标记所有问题,而人工审查员要找出散布在大型拉取请求中的相同问题,则需要更长的时间。
这种速度差异正是此处的核心价值所在。这些规则本身并无突破性——大多数经验丰富的工程师早已凭直觉掌握这些知识。不同的是,现在这些规则能够以一致且快速的方式被应用,而人工审核员,尤其是那些已经进行到当天第三次审核的人,根本无法保持这样的效率。
常被忽视的益处:注重教学而非单纯执行
真正改变状况的并非那些性能检查本身,而是观察新加入团队的成员如何使用该工具。此人加入团队仅几个月,仍在熟悉代码库。在提交拉取请求之前,他们先请自己的技术顾问进行审核。顾问发现了瀑布式执行模式,没有仅仅标记问题,而是用通俗的语言——直接结合具体规则——解释了在那种特定情况下并行执行这些操作为何如此重要。这与那些仅输出规则编号和简短提示、需另行查找解释的代码检查工具相比有着本质不同。这种体验更像是资深工程师留下的真正有用的评审意见,只不过反馈是在拉取请求还未进入草稿阶段时就已出现。
这或许才是此处更值得关注的用例,而非“人工智能能写出更整洁的代码”。它更接近于“人工智能能够持续培养更好的工作习惯”,且无需有人专门抽出时间进行指导,也无需编写那些半年内就会过时的入门文档。当一个团队安装了五十个相互重叠的技能文件——每个文件都有各自的观点,其中一些难免会与其他文件产生冲突——时,这种优势是否依然存在仍是个未解之谜。但对于一个由一名经验丰富的工程师和几名仍在摸索中的人组成的小团队而言,它已然展现出强大的效能提升作用。
现状与未来
该功能最终被纳入了共享团队配置中,主要是因为其弊端极小,而带来的好处——让开发人员不再编写传统瀑布式代码——是值得付出的合理代价。目前尚不清楚这种模式是否会成为框架向 AI 智能体传递功能方式的默认标准,还是仅仅会成为另一个配置文件,在新鲜感消失且无人愿意更新它之后逐渐被废弃。这是个值得在六个月后再探讨的问题,而非现在就给出答案。
相关阅读
- 深入了解 TypeScript 7 的 Go 重写机制:无需修改代码即可提升速度——了解 TypeScript 7 基于 Go 的编译器如何实现8到12倍更快的构建速度,为何这种架构变革有效,以及如何安全地升级现有项目。