首页
/ React Router Agent Skill 解析:基于 SKILL.md 的模式识别、引用文档与源码级分发机制

React Router Agent Skill 解析:基于 SKILL.md 的模式识别、引用文档与源码级分发机制

2026-09-06 09:31:22作者:晏闻田Solitary

React Router 官方仓库在 .agents/skills/react-router/ 下内置了一个面向 AI 编码代理(Agent)的技能定义文件 SKILL.md,它以“先识别应用模式、再加载对应参考文档、最后以安装包内文档为事实来源”为核心工作流,指导 Agent 正确修改 Framework、Data、Declarative 以及不稳定 RSC 四种模式下的 React Router 应用。本文完整拆解该 Skill 的模式判别规则、四份参考文档的职责边界、node_modules/react-router/docs/ 随包分发机制,以及 Skill 自身随 create-react-router 发布的构建管线,帮助读者既能在自己的项目中正确套用这套技能,也能理解其背后的工程实现。

SKILL.md 是什么:一份给 AI 代理的操作手册

SKILL.md 是一份标准的 Agent Skill 文件,文件头部以 YAML frontmatter 声明了元信息:

---
name: react-router
description: Build applications with React Router in Framework, Data, Declarative, and unstable RSC modes. Use when configuring routes, route modules, loaders, actions, forms, fetchers, navigation, pending UI, SSR/SPA/pre-rendering, middleware, URL params/search params, or React Router upgrades.
license: MIT
---

description 字段枚举了该技能触发时的典型场景:路由配置、route modules、loaders/actions、表单与 fetchers、导航、pending UI、SSR/SPA/预渲染、中间件、URL 参数以及版本升级。正文开篇即给出总纲:“React Router is mode-specific. Before changing an app, identify the mode, load the matching reference, then read the installed docs for the installed package version.”(React Router 是模式相关的:改动应用之前,先识别模式,加载匹配的参考文档,再阅读与安装包版本一致的文档)。

这与普通项目文档最大的区别在于:它不是“讲原理”,而是“规定流程”——它约束的是 Agent 在动手改代码前的信息装载顺序,防止把 Framework 模式的路由模块约定错套到 Declarative 应用上。

核心工作流第一步:识别应用模式

Skill 要求“除非有意做模式迁移,否则不要把 Framework/Data 模式的做法应用到 Declarative 应用上”,并为每种模式给出了可观察的识别特征(即代码/文件层面的证据清单)。

Framework 模式

出现以下任一特征时,判定为 Framework 模式:

  • 依赖中包含 @react-router/dev
  • 存在 react-router.config.ts
  • 存在 app/routes.ts
  • 存在 app/entry.server.tsx 和/或 app/entry.client.tsx
  • app/routes/ 下有路由模块;
  • 路由模块导出了 loaderactionclientLoaderclientActionErrorBoundarymetalinksheaders 等;
  • ./+types/... 导入生成的路由类型;
  • Vite 配置使用了来自 @react-router/dev/vite 的 React Router 插件。

Skill 特别提醒:示例通常假设默认 app/ 目录,但在假设确切路径之前,要先检查 react-router.config.ts 中是否自定义了 appDirectory。这一条在本仓库中可以直接得到印证——例如 playground/framework/vite.config.tsplayground/framework/react-router.config.ts 就是典型的 Framework 应用配置组合。

Data 模式

出现以下特征时判定为 Data 模式:

  • 使用了 createBrowserRoutercreateHashRoutercreateMemoryRoutercreateStaticRouter
  • 渲染使用了 <RouterProvider router={router}>
  • 路由对象带有 pathchildrenloaderactionComponentErrorBoundarylazy 等属性;
  • 使用 data APIs 但没有 Framework Vite 插件。

Declarative 模式

出现以下特征时判定为 Declarative 模式:

  • 使用了 <BrowserRouter><HashRouter><MemoryRouter>
  • 通过 <Routes><Route> JSX 配置路由;
  • 路由组件以 element={<Component />} 形式传入;
  • 没有 data router、没有路由模块约定、没有 loaders/actions。

RSC 模式(不稳定)

React Server Components 支持目前是不稳定的(unstable),且同时存在 Framework 与 Data 两个变体。识别特征包括:unstable_reactRouterRSC@vitejs/plugin-rscunstable_RSCRouteConfigentry.rsc 等 RSC 入口文件、ServerComponent/ServerErrorBoundary/ServerLayout/ServerHydrateFallback 导出,以及 "use client""server-only""client-only" 等 React 指令或边界包。RSC Framework 需要同时阅读 framework 与 RSC 两份参考;RSC Data 则需要同时阅读 data 与 RSC 两份参考。本仓库中 playground/rsc-vite/vite.config.ts 等示例即属于这一类应用形态。

四份参考文档:references/ 的职责划分

模式识别完成后,Skill 指示 Agent 加载 .agents/skills/react-router/references/ 下对应的参考文档:

参考文档 适用场景
references/framework-mode.md Framework 模式,或 RSC Framework 的基础行为
references/data-mode.md Data 模式,或 RSC Data 的基础行为
references/declarative-mode.md Declarative 模式
references/rsc.md 任何不稳定的 RSC 应用

下面按文档内容展开每份参考的核心规则。

Framework 模式参考:路由模块是核心单元

framework-mode.md 首先给出典型的路由模块形状,展示生成的类型如何使用:

import type { Route } from "./+types/product";

export async function loader({ params }: Route.LoaderArgs) {
  return { product: await getProduct(params.productId) };
}

export default function Product({ loaderData }: Route.ComponentProps) {
  return <h1>{loaderData.product.name}</h1>;
}

它整理了路由模块常用导出的职责表:

导出 用途
default 匹配时渲染的路由组件
loader 服务端数据加载(SSR/预渲染/服务端数据请求)
clientLoader 仅浏览器的数据加载,或补充服务端 loader 数据
action <Form>useSubmit 或 fetchers 调用的服务端变更
clientAction 仅浏览器的变更,或服务端 action 的客户端包装
ErrorBoundary 本路由 loader/action/组件抛错时的 UI
HydrateFallback 客户端 loader 水合期间的初始回退
links / meta 路由的 document 链接与元数据
handle 通过 useMatches 消费的任意路由元数据
shouldRevalidate 覆盖默认的 loader 重验证行为
middleware / clientMiddleware 启用后的服务端/客户端请求管线钩子

它还给出了若干强约束规则,可直接作为团队规范使用:

  • 路由配置放在 app/routes.ts,多数应用用文件系统路由(flatRoutes()),也支持手动配置;
  • app/root.tsx 是根路由,应承载全局文档/应用壳层职责;不应把本应共享 UI 或数据边界的路由拍平;
  • 路由数据优先用 loader/clientLoader 加载、action/clientAction 变更,而不是散落的 useEffect 取数;
  • 服务端专属代码(Node-only/数据库)必须放在 server-only 模块中,从 loader/action 调用,而非浏览器渲染的组件代码;
  • 常见模式:action 校验失败返回 data({ errors, values }, { status: 400 }),loader 中记录不存在则抛 data("Not Found", { status: 404 }),搜索/过滤状态解析 loader 中的 URL 使其可分享、可收藏;
  • 表单选择:更新 URL 的搜索表单用 <Form method="get">,需要改历史或完成后重定向的变更用 <Form method="post">,留在原页的变更用 useFetcher;乐观 UI 从 fetcher.formDatanavigation.formData 派生;
  • 类型安全:从 ./+types/<route> 导入 Route.LoaderArgsRoute.ActionArgsRoute.ComponentProps,不要手改 .react-router/types 下的生成文件;
  • meta 接收 loaderData,不要使用已废弃的 data 参数;
  • 中间件、session 与鉴权 API 对版本和配置敏感,实现前先核对已安装的 React Router 版本和应用的 react-router.config.ts

Data 模式参考:手动装配的数据路由

data-mode.md 说明 Data 模式提供路由对象、loaders、actions、pending UI、fetchers 和 SSR 原语,但不引入 Framework Vite 插件与路由模块文件约定。典型装配代码如下:

import { createBrowserRouter, RouterProvider } from "react-router";

const router = createBrowserRouter([
  {
    path: "/",
    Component: Root,
    loader: rootLoader,
    children: [
      { index: true, Component: Home },
      {
        path: "projects/:projectId",
        Component: Project,
        loader: projectLoader,
      },
    ],
  },
]);

root.render(<RouterProvider router={router} />);

其规则要点包括:路由对象尽量放在渲染之外;嵌套路由承载共享布局与数据边界;示例中优先用 Component/ErrorBoundary 属性(除非既有应用统一用 element)。导航规则与 Framework 一致(<Link>/<NavLink> 用于用户主动导航、loader/action 中用 redirect、事件回调里用 useNavigate),且强调把 URL 参数当作字符串来校验与解析、避免无意丢掉无关的 search params。SSR 部分特别指出 Data 模式的 SSR 是“手动且更接近底层”的:改 SSR 之前先阅读 react-router/docs/start/data/custom.md,并在现有服务端抽象中寻找 createStaticHandlercreateStaticRouterStaticRouterProvider 与水合数据处理,保持既有模式一致。

Declarative 模式参考:能力边界要清晰

declarative-mode.md 展示了最简单的形态:

import { BrowserRouter, Routes, Route } from "react-router";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="about" element={<About />} />
        <Route path="dashboard" element={<DashboardLayout />}>
          <Route index element={<DashboardHome />} />
          <Route path="settings" element={<Settings />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

这份参考最有价值的部分是“模式边界”一节:Declarative 模式没有 loaderaction<Form>useFetcheruseNavigation、路由模块导出和生成的 ./+types 类型。当用户在这些应用里提出路由级数据加载、CRUD、表单变更、重验证、pending UI 或 fetchers 等需求时,Skill 明确要求:根据用户想要的结构程度推荐迁移到 Data 或 Framework 模式,且在用户尚未明确要求迁移时先询问——这是防止 Agent 擅自做大改动的护栏。

RSC 参考:不稳定 API 的双变体

rsc.md 强调 RSC 支持不稳定,分两个变体:

  • RSC Framework 模式:Framework 模式 + 不稳定的 RSC Vite 插件。识别特征包括从 @react-router/dev/vite 导入 unstable_reactRouterRSC@vitejs/plugin-rscvite.config.tsplugins: [reactRouterRSC(), rsc()]、RSC 入口文件如 entry.rsc。特别警告:RSC Framework 模式使用不同的 Vite 插件,不要把它换成普通的 reactRouter() 插件
  • RSC Data 模式:更底层的手动集成,识别 unstable_RSCRouteConfigunstable_matchRSCServerRequestunstable_routeRSCServerRequestunstable_RSCHydratedRouterunstable_RSCStaticRouter 等 API 以及自定义的 bundler/server 配置。

路由模块层面,RSC 引入了成对的导出概念:ServerComponent(替代普通客户端 default 组件)、ServerErrorBoundary 配对 ErrorBoundaryServerLayout 配对 LayoutServerHydrateFallback 配对 HydrateFallback;loader/action 还可以返回服务端渲染的 React 元素。同一角色不能同时导出客户端组件与服务端组件。客户端/服务端边界方面,需要 hooks、浏览器 API 或事件处理器的组件用 "use client";服务端数据访问与机密放 server-only 模块;并且明确指出不要假设 .server/.client 文件命名约定在 RSC Framework 模式下与常规模式行为相同。稳定性要求也很直白:实现或重构 RSC 代码前,核对已安装的 React Router 版本与 @vitejs/plugin-rsc 版本,阅读应用既有的 RSC 入口/配置,优先做与当前模式一致的最小改动。

以安装包文档为“事实来源”:node_modules/react-router/docs/

SKILL.md 最具工程特色的设计是“Use Installed Docs as Source of Truth”一节。它指出 React Router 包随 npm 包附带了 markdown 文档,使指导内容与用户安装的版本严格一致:

node_modules/react-router/docs/

关键路径:

node_modules/react-router/docs/index.md
node_modules/react-router/docs/start/
node_modules/react-router/docs/how-to/
node_modules/react-router/docs/explanation/
node_modules/react-router/docs/upgrading/

当 Skill 引用 react-router/docs/... 时,Agent 应读取 node_modules/react-router/docs/ 下的对应文件;若安装版本未附带本地文档,在 React Router 仓库内工作时则使用仓库 docs/ 目录,在消费方应用中回退到版本对应的官网文档。

这一机制在本仓库中有明确的构建实现证据

  1. packages/react-router/scripts/copy-docs.mjs 在构建时把仓库 docs/ 的一部分复制进 react-router 包目录(排除 apicommunitytutorials 三个顶层目录以及 elements.md 等非目标文件),脚本注释直白说明了目的:“so it ships to npm and is available via react-router/docs/... package exports for AI coding agents and the React Router agent skills”(使其随 npm 分发,可通过 react-router/docs/... 包导出供 AI 编码代理和 React Router 技能使用);
  2. packages/react-router/package.jsonprepublishOnly 钩子执行该脚本,且 files 列表包含 "docs/",保证发布物中包含文档;
  3. packages/create-react-router/scripts/copy-agent-skills.mjs 则在 create-react-router 打包前(prepack)把 .agents/skills/react-router/ 整个目录复制到 dist/agent-skills/react-router,让脚手架包也能携带这份技能。

也就是说:用户在 create-react-router 里创建的新应用,既随 react-router 包获得了与版本匹配的本地文档,其脚手架包中也自带了本技能——这正是 SKILL.md 中“read the installed docs for the installed package version”能成立的前提。

MODES 标记:文档与模式的匹配过滤器

SKILL.md 还定义了文档级别的模式标记约定:多数文档开头附近带有形如 [MODES: framework, data, declarative] 的标记,只有当标记与当前应用模式匹配时,该文档的结论才应被套用;跨模式任务优先选择与当前应用匹配的文件。这一约定可以在仓库文档中直接验证,例如本仓库 docs/ 下大量文档都携带该标记:[docs/how-to/spa.md](https://gitcode.com/GitHub_Trending/re/react-router/blob/917e6fdc0f8beb141e3380e83e27634d7be84e1d/docs/how-to/spa.md?utm_source=gitcode_repo_files) 标注 [MODES: framework][docs/how-to/fetchers.md](https://gitcode.com/GitHub_Trending/re/react-router/blob/917e6fdc0f8beb141e3380e83e27634d7be84e1d/docs/how-to/fetchers.md?utm_source=gitcode_repo_files) 标注 [MODES: framework, data][docs/how-to/data-strategy.md](https://gitcode.com/GitHub_Trending/re/react-router/blob/917e6fdc0f8beb141e3380e83e27634d7be84e1d/docs/how-to/data-strategy.md?utm_source=gitcode_repo_files) 标注 [MODES: data],而 [docs/how-to/accessibility.md](https://gitcode.com/GitHub_Trending/re/react-router/blob/917e6fdc0f8beb141e3380e83e27634d7be84e1d/docs/how-to/accessibility.md?utm_source=gitcode_repo_files) 则覆盖全部三种模式。RSC 相关文档主要见 docs/how-to/react-server-components.md

模式迁移文档索引

当用户显式要求切换模式时,SKILL.md 给出一份“目标模式参考 + 迁移相关文档”的映射表:

迁移 应阅读的文档
Declarative → Data react-router/docs/start/modes.mdreact-router/docs/start/data/routing.mdreact-router/docs/start/data/data-loading.mdreact-router/docs/start/data/actions.md
Declarative/Data → Framework react-router/docs/start/modes.mdreact-router/docs/start/framework/routing.mdreact-router/docs/start/framework/route-module.mdreact-router/docs/how-to/route-module-type-safety.md
Framework 的 SPA/SSR/预渲染调整 react-router/docs/start/framework/rendering.mdreact-router/docs/how-to/spa.mdreact-router/docs/how-to/pre-rendering.mdreact-router/docs/start/framework/data-loading.mdreact-router/docs/start/framework/actions.md
Future flags / 升级 react-router/docs/upgrading/future.mdreact-router/docs/upgrading/ 下相关文件

其中所有 react-router/docs/... 路径都指向前文所述的安装版本文档(或本仓库 docs/ 目录),例如 docs/start/modes.mddocs/upgrading/v7.md。这张索引本质上是把“迁移”拆成可验证的文档阅读清单,避免 Agent 凭记忆拼接迁移步骤。

实践启示:从这份 Skill 中可以借鉴的三点

  1. 先分类,后动手。React Router 同一套 API 在四种模式下行为差异很大(例如 Declarative 没有 loader、RSC Framework 不能用普通 reactRouter() 插件),Skill 把“识别模式特征”放在一切修改之前,这套“证据清单式”的判别方法可以直接移植到其他多模式框架中;
  2. 让文档与安装版本绑定。通过构建脚本把 docs 打进 npm 包,并用 [MODES: ...] 标记过滤适用性,是解决“Agent 引用了过新/过旧文档”这一常见问题的务实方案;
  3. 为 Agent 设置护栏。参考文档中反复出现的“改之前先读某文档”“不要假设路径/命名约定”“迁移前先询问”等表述,都是在压缩 Agent 的擅自发挥空间——这类约束性写法对编写你自己的项目级 Agent 技能文档很有参考价值。

综上,.agents/skills/react-router/SKILL.md 与其四份 references、node_modules 随包文档、以及两条构建复制管线(copy-docs.mjscopy-agent-skills.mjs)共同构成了 React Router 官方“版本感知、模式感知”的 Agent 辅助体系。理解这套体系,既能帮助你在多模式 React Router 项目中安全地引入 AI 辅助开发,也能为设计其他框架的 Agent 技能提供工程范本。

登录后查看全文
热门项目推荐
相关项目推荐