React Router 开放治理模型:从指导委员会到六阶段 RFC 的功能落地流程
React Router 自 Remix 并入之后,从"创始开发者主导"转向了以指导委员会(Steering Committee, SC)为核心的开放治理模型,并通过一套参照 TC39 设计的六阶段 RFC 漏斗决定每个新功能的生死。本文基于仓库根目录的 GOVERNANCE.md 展开,结合仓库中的实际流程工件(bug 报告测试模板、变更文件工具链、ADR 目录等),讲清如何提交 Bug、如何推动一个新特性从 Proposal 走到 Stable,以及这一套流程在会议记录中的真实运转痕迹。
一、治理模式是如何形成的
从项目文档记载看,React Router 自 2014 年起长期由 Michael Jackson 与 Ryan Florence 主导开发。2021 年 Remix 发布、Remix 团队组建,再到 Remix v2 与 React Router v7 合并,项目的治理结构随之从 Founder-Leader(创始开发者领导)模型切换为 Steering Committee 模型,日常运转依赖 Request for Comments(RFC)流程。
GOVERNANCE.md 被明确定位为一份 evergreen 文档——它会随流程变化持续更新,目标是说清两件事:项目将如何继续演进,以及新特性以何种方式进入代码库。配套的 API 开发策略文档 则从使用者视角解释了同一套机制的落地产物:unstable 标志与 future 标志。
二、五条设计目标:评估 RFC 的基准
文档给出五条设计目标,任何 RFC 在被接受时都应对照考量:
- Less is More(少即是多):React Router 这些年积累了大量功能,也带来了大量 API 表面。方向是聚焦核心功能、在不牺牲能力的前提下收缩 API 表面——例如把若干既有 API 收敛为一个,或弃用旧 API 改用新的 React API。
- Routing and Data Focused(以路由与数据为中心):聚焦与路由器深度集成的核心 API,避免添加那些本可以在用户代码中自行实现的一等 API。
- Simple Migration Paths(平滑迁移路径):大版本升级不应该痛苦。破坏性变更应放在 future flag 之后;弃用应提前在代码和文档中明确标注;大版本发布前应先加入 Console 警告,引导开发者提前开始适配。
- Lowest Common Mode(最低共同模式):功能应加在尽可能低的使用模式上(
declarative -> data -> framework),再被上层模式复用,确保最大数量的 React Router 应用可以受益。 - Regular Release Cadence(规律的发版节奏):目标大约每年发布一个 SemVer 大版本,让应用开发者有足够时间提前准备。
仓库中的工件能佐证这些目标不是空话:
decisions/目录以 ADR(Architecture Decision Records)形式归档了已定案的重要决策,编号从 0001-use-blocker.md 一直到 0016-plan-remove-agnostic-types.md,并提供了统一的 模板(Context / Decision / Consequences 三段式),对应"Less is More"下对 API 决策的书面留痕。- 2025-11-04 的 SC 会议记录确认了大版本节奏的具体化:"计划 v8 落在 2026 年 Q2,与 Node 20 的 EOL 对齐;此后目标是在每年同一 Q2 窗口发布大版本"。而当前仓库快照中 packages/react-router/package.json 的版本号已是 8.3.0,说明"每年一个大版本"的设计目标已经从计划变成了现实。
三、指导委员会(SC):职责与运作方式
SC 的三项核心职权:
- 接受 RFC 进入"考虑"阶段;
- 批准以"unstable"状态落地特性的 PR;
- 批准将特性稳定化(stabilization)的 PR。
初始成员为原 Remix 团队开发者共 7 人:Matt Brophy(@brophdawg11)、Pedro Cattori(@pcattori)、Mark Dalgleish(@markdalgleish)、Jacob Ebey(@jacob-ebey)、Brooks Lybrand(@brookslybrand)、Sergio Xalambrí(@sergiodxa)、Bryan Ross(@rossipedia)。文档同时说明,未来可能会有限度地吸纳深度参与的社区成员加入 SC。
为降低协作摩擦,SC 主要通过 GitHub 异步工作,必要时再安排私下或公开的会议。
四、Bug/Issue 流程:"最小且可运行"的复现
由于使用 React Router 的应用数量庞大,文档要求对 Issue 提交保持严格,避免 GitHub 过载:
- 所有 Bug 必须有**最小(minimal)且可运行(runnable)**的复现:
- 最小:不是指向一个部署站点或你现有应用中的某个分支;
- 可运行:是一个能看到问题的工作应用,而不是需要手工拼装的几段代码;
- 首选复现方式:
- Framework Mode:StackBlitz,或一个基于 integration/bug-report-test.ts 的、带失败集成测试的 GitHub fork;
- Data/Declarative Modes:CodeSandbox 模板(TS 或 JS);
- 如果 StackBlitz/CodeSandbox 不可行,基于全新
npx create-react-router应用生成的 GitHub 仓库也可以接受; - 只有在极其特殊的情况下,才会接受代码片段或"最大复现"。
- Issue 审查:不满足上述标准的 Issue 会被关闭并指回本文档;非 Issue(功能请求、使用问题)同样会被关闭并给出链接;SC 会定期分诊(triage)。
- 修复 Issue:SC 会给优质的社区 Issue 打上
Accepting PRs标签,这类 Issue 通常是面小、易于修复的;任何人都可以处理任何 Issue,但如果改动面太大、核心成员来不及快速评审,则不保证 PR 被接受。
仓库里的"失败测试"模板
docs/community/contributing.md 明确把"一个带失败测试的 PR"列为 Bug 报告的最好形式,并特别警告:不要以 PR 的形式直接发起新功能——新功能必须走本文档的流程。仓库为此内置了一个专门的模板文件 integration/bug-report-test.ts,其开头注释就是一份操作指南:
- 你不需要修好 Bug,这个 PR 只需要"失败",用于让团队看到错误行为;如果你恰好有修复方案,要在后续 commit 中应用,并把此时变绿的测试移入正式测试文件;
- 模板基于 Playwright 构建:
test.beforeEach中对.data请求注入 50ms 延迟以稳定测试,createFixture用内联的app/routes/_index.tsx与app/routes/burgers.tsx组装一个真实应用,再由createAppFixture交给 Playwright 驱动页面交互; - 模板注释给出完整的本地运行方式:
pnpm install && pnpm build
# 如未装过 Playwright 浏览器内核:
pnpm exec playwright install chromium
# 运行这个 bug 报告测试:
pnpm test:integration bug-report --project chromium
# 加 --watch 可在文件变化时自动重跑
pnpm test:integration bug-report --project chromium --watch
五、新功能流程:六阶段 RFC 漏斗
新特性的流程"大致基于 TC39 流程"。文档强调两点:进入某个阶段并不意味着 RFC 一定会走到后面(阶段是一个漏斗,越少数的 RFC 能进入越靠后的阶段,只有最强的 RFC 才会以稳定形式进入发布);大多数社区驱动的功能会走完全部阶段,但若某功能足够 trivial/显而易见,可以跳级直接以稳定功能实现。
阶段总览
| 阶段 | 名称 | 进入条件 | 目的 |
|---|---|---|---|
| 0 | Proposal(提案) | 在 GitHub 上开启 Proposal 讨论 | 以 GitHub 提案作为最低的 RFC 提交门槛。任何人都可以提交,社区可以评审、评论、点赞,且初期不需要 SC 参与。 |
| 1 | Consideration(考虑) | 获得 2 名 SC 成员接受提案 | 第一道"漏斗":SC 正式表达对热门 RFC 的兴趣。仅需 2 名成员表态即可进入考虑阶段,以便低摩擦地在 Alpha 阶段试验特性。 |
| 2 | Alpha(试验) | 开一个以 "unstable" 状态实现该特性的 PR | 下一道漏斗。SC 表态兴趣后,开放一个示例 PR 实现,让社区成员在不依赖任何 SemVer 发布的情况下进行 alpha 测试。此阶段用于在实际应用中评估 RFC、考察务实的代码实现形态。 |
| 3 | Beta(公测) | 2 名 SC 成员批准该 PR(认可其作为不稳定 API) | SC 成员不仅对 beta 特性代码满意,还看到 alpha 测试者的正面反馈后,RFC 进入 Beta。Alpha 阶段 PR 攒够 SC 批准即可合并,并进入下一个 React Router 发布。 |
| 4 | Stabilization(稳定化) | 在 Beta 阶段至少停留 1 个月,且开一个稳定化 API 的 PR;PR 应同时包含新功能的文档 | 确保不稳定特性有足够时间供应用方升级版本并选择 beta 测试,不赶进度,以便在稳定化前获得最大量的反馈。 |
| 5 | Stable(稳定) | 至少 50% 的 SC 成员批准稳定化 PR | SC 不仅认可稳定特性的代码,还看到 beta 测试者的正面反馈。Beta 阶段 PR 攒够批准并满足 Beta 最低时长后即可合并,进入下一个 React Router 发布。 |
文档还说明:特性一旦到达 Stage 2,就会被加入官方 Roadmap 供社区跟踪其阶段进展。
Stage 0 — Proposal
- 所有新功能都从 Stage 0 开始:以 RFC 形式写在 GitHub Proposal Discussion 中;
- 任何人都可以写 RFC,包括核心团队成员和社区成员;
- RFC 应说明:新特性的使用场景、为什么现有 API 不足以覆盖该场景,并给出候选的 API 形态;
- 提案应清晰、简洁,提供足够上下文供 SC 与社区评估其价值;
- 社区点赞是兴趣与需求的信号——点赞更高的提案更可能被 SC 考虑;
- 此阶段社区成员可以在 fork 中做示例实现并在 RFC 中贴链接,但不应在达到 Stage 1 之前开 PR。
Stage 1 — Consideration
- 当 2 名 SC 成员表示支持该想法是 React Router 的有价值补充时,提案进入 Stage 1;
- 这两位初始支持者成为该特性的"champion",松散地负责护送特性走过后续阶段;
- 此阶段提案有资格获得来自核心团队或社区成员的示例 PR;
- SC 会在此阶段明确该特性是接受社区 PR,还是核心团队自己来做;
- 若接受社区 PR,会给 RFC 加
accepting-prs标签; - 此阶段的所有 PR 都应以"unstable"方式实现(通常是对 future flag 或 API 使用
unstable_前缀)。
Stage 2 — Alpha
- PR 以
unstable_状态实现该特性后,提案进入 Stage 2; - 此时应为该 Proposal 开一个 Issue 并加入 Roadmap;移除
accepting-prs标签、加上🗺️ Roadmap标签,表示该 RFC 正式进入路线图; - 此阶段的核心是:在合并任何代码之前寻找早期社区测试,因此 PR 需要提供一种让社区成员选择加入 alpha 测试的机制:
- 维护者可以给 PR 分支加
alpha-release标签触发一次 alpha 实验性发布,并把结果评论回 PR; - 由于 alpha 发布可能包含已提交到
dev但尚未随稳定版发布的其他工作,某些场景下并不适合测试; - 这种情况下,PR 作者也可以在评论里附上
.patch文件内容,社区可以用 patch-package 或 pnpm patch 应用;
- 维护者可以给 PR 分支加
- alpha 测试者的反馈是继续推进的必要条件;
- PR 还应包含一个 changes 文件,用于记录新 API 以进入 release notes;
- SC 成员通过 GitHub review 评审并批准 PR。此阶段的批准传达四层含义:特性对 React Router 有价值;API/代码足以进入 unstable/beta 测试(尽管可能还要迭代);代码不必是最终形态,但不能对其他 API 区域引入回归;alpha 测试者的正面反馈已经足够。
Stage 3 — Beta
- 拿到 2 名 SC 成员的 Stage 2 PR 批准并合并到
dev后,提案进入 Stage 3;- 如果
unstable_PR 的作者本身就是 SC 成员,其作者身份算作一次隐式批准,此时还需要另外 1 名 SC 成员的显式批准;
- 如果
- 特性随下一个正常 SemVer 发布进入更广泛的 beta 测试,位于
unstable_标志之后。
Stage 4 — Stabilization
- 在 Stage 3 至少停留 1 个月后,开一个移除
unstable_前缀、稳定化特性的 PR,提案进入 Stage 4; - 稳定化 PR 应补上该功能的正式文档;
- SC 成员通过 GitHub review 评审批准。此阶段的批准传达三层含义:beta 测试者反馈已足以让人信任 API 的设计与实现;代码达到生产质量、测试充分且无相关回归;PR 包含稳定功能的文档。
Stage 5 — Stable
- 拿到至少 50% SC 成员的 Stage 4 PR 批准并合并到
dev后,提案进入 Stage 5;- 稳定化 PR 的作者是 SC 成员时,其作者身份算一次隐式批准;
- 稳定特性随下一个正常 SemVer 发布进入正式版本。
六、unstable 标志与变更文件:流程在代码中的落点
Stage 1–5 并非只在文档里流转,仓库中有对应的机制支撑:
unstable 与 future 标志的区分。 docs/community/api-development-strategy.md 把标志分为两类:破坏性 API 变更先以 future flag 形式引入,让用户在大版本前逐个 opt-in;而 unstable flag 用于尚在设计的特性——不推荐用于生产、可能无预警变更、可能有 Bug、没有文档、甚至可能被整体放弃。该文档还给出了版本策略:unstable 标志因为是"非新稳定 API",随 SemVer patch 版本发布;当它稳定为 future flag 时,则以 minor 版本发布并补充文档。这与 GOVERNANCE 中 Stage 2/3 的 unstable_ 前缀、Stage 4 的"移除前缀 + 补文档"直接对应。从源码结构看,unstable_ 前缀 API 在仓库中真实存在并被持续测试,例如 packages/react-router/index.ts 与 packages/react-router/lib/hooks.tsx 中的 unstable 系列 hook,以及配套测试 packages/react-router/tests/unstable-useRouterState-test.tsx;框架模式的 unstable 配置项(如 unstable_splitRouteModules、unstable_optimizedDeps)则在 packages/react-router-dev/config/config.ts 中定义。
changes 文件与版本推进。 Stage 2 要求"PR 应包含 changes 文件",这一要求在 docs/community/contributing.md 中有更具体的规定:所有对用户有影响的 PR 都应在相关包的 packages/<package>/.changes/ 目录下生成变更文件,可用 pnpm run changes:add 工具生成;文件命名为 <type>.<short-description>.md,type 取 patch、minor、major、unstable 四种之一,例如:
patch.fix-fetcher-redirects.md
minor.add-some-new-api.md
major.require-node-24.md
unstable.update-unstable-api.md
解析与校验逻辑集中在 scripts/changes/changes.ts:bumpTypes 定义了四种 bump 类型;parsePackageChanges 会校验文件名前缀、文件非空、首行不能以 - 开头的 bullet 开头(changelog 会自动加 bullet)、内部标题只能是 4–6 级、带 BREAKING CHANGE: 前缀的内容必须用 major. 前缀等。发布侧采用锁步(lock-step)版本策略——generateCommitMessage 直接以 Release v<nextVersion> 生成提交信息,DEVELOPMENT.md 则描述了整套自动化:main 分支上出现 changes 文件即触发 release 工作流,创建 release-v<major>-pr 分支、更新版本、生成 changelog、删除 changes 文件并开 PR,合并后再自动发布到 npm、打 tag、创建 GitHub Release。也就是说,GOVERNANCE 中"Stage 3 进入下一个正常 SemVer 发布"这句话,最终是由这套工具链兑现的。
七、从会议记录看流程的实际运转
GOVERNANCE.md 的"Meeting Notes"一节是 SC 会议的持续归档区,文档内甚至内嵌了笔记模板(<details> 折叠块 + YYYY-MM-DD Meeting Notes 标题)。当前文档中已归档六次会议(2025-09-08、2025-09-23、2025-11-04、2025-11-18、2025-12-02、2025-12-16),它们恰好是上述流程运转的样本:
| 日期 | 关键结论(节选) |
|---|---|
| 2025-09-08 | 复盘 Roadmap:middleware 与 context 已合并进 dev 等待 7.9.0 预发布;onError 已在 7.8.2 发布且表现符合预期;RSC 框架模式接近完成、剩余渲染期错误处理;讨论 observability 与 OpenTelemetry 的集成路径;决定聚焦在途事项,不再接收新提案(当时已有 10+ 提案在处理中)。 |
| 2025-09-23 | 宣布 7.9.2 将发布 unstable 的 RSC 框架模式支持与 fetcher.unstable_reset() API;评审 instrumentRouter/instrumentRoutes 的 POC,并讨论改为只读信息子集以防用户篡改 handler 参数;推进 2 个新 RFC 进入"考虑"阶段(Prerender concurrency、Per-route Layout component)。 |
| 2025-11-04 | 评审 v8 开放提案:确认改为 ESM-only 构建;计划 v8 落在 2026 Q2 并与 Node 20 EOL 对齐,v8 最低 Node 版本 22.12;此后每年同一 Q2 窗口发大版本;SRI 准备稳定化但需先征询既有用户;unstable_optimizedDeps 在 v8 保持 unstable;RSC 实现不进 v8 稳定 API。 |
| 2025-11-18 | 启动 fetcher.reset 与客户端 onError 的稳定化 PR;确认 split route modules 与 environment API 可批量稳定化;讨论类型安全 fetcher(route ID vs pattern、拆分为 useRouteLoader/useRouteAction、借助 React 19 的 useTransition/useOptimistic 瘦身状态抽象)以及"default revalidate"的调用点设计。 |
| 2025-12-02 | 三项稳定化落地:environment API、split route modules、fetch error reset 的 future flag;onError 待内部重构解决 strict mode 下可能的双重上报后随下个版本发布;讨论 Babel 转 SWC/Oxide 的性能提案(需要更多瓶颈证据);讨论 fetcher 错误不向路由级错误边界冒泡的 opt-in 机制、路由 masking/rewrites、非 window 元素的滚动恢复等提案。 |
| 2025-12-16 | 修复尾斜杠导致 loader/action 收到不一致请求路径的 Bug:数据请求 URL 改为 /_a/b/c/_.data 形态(原为 _root.data 风格),因可能破坏缓存规则而放在 future flag 之后,opt-in 且基本非破坏。 |
这些记录展示了文档中每个流程条款的实例:Stage 2 的 alpha 试验(RSC 框架模式以 unstable 状态先入 7.9.2)、Stage 4 的稳定化批次(三个 future flag 一起批处理)、以 future flag 承载潜在破坏性变更(尾斜杠数据请求格式)——与 GOVERNANCE.md 的设计目标"破坏性变更应放在 future flag 之后"逐条对应。
八、小结:一套可对照仓库验证的流程
React Router 的开放治理模型可以浓缩为三条主线:
- 准入:Bug 必须"最小且可运行"(首选 integration/bug-report-test.ts 式的失败测试 PR);新功能必须从 Proposal 讨论起步,而不是直接开 PR。
- 分级推进:Stage 0→5 的漏斗中,
unstable_前缀承载 Stage 1–3 的实验期,changes 文件(patch/minor/major/unstable)驱动 SemVer 推进,Stage 4 强制"Beta 至少 1 个月 + 文档齐备",Stage 5 要求 50% SC 批准。 - 留痕与节奏:
decisions/目录的 ADR、GOVERNANCE.md 内嵌的会议纪要、以及 DEVELOPMENT.md 描述的自动化发布管线,共同让"每年一个大版本、破坏性变更走 future flag"成为可执行、可审计的制度,而不只是一句口号。
对贡献者而言,实际可操作的入口很明确:Bug 找 integration/bug-report-test.ts,新 API 找 GitHub Proposal Discussion 并阅读 GOVERNANCE.md 与 docs/community/contributing.md,PR 中记得带上 changes 文件,剩下的交给漏斗。
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 StartedRust0623
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