首页
/ Awesome Copilot React 19 Upgrade 插件:React 18 到 React 19 企业级迁移工具链实战指南

Awesome Copilot React 19 Upgrade 插件:React 18 到 React 19 企业级迁移工具链实战指南

2026-09-10 16:35:16作者:翟江哲Frasier

本指南围绕开源仓库 awesome-copilot 中的 react19-upgrade 插件(插件清单插件文档)展开,讲解如何借助其内置的 5 个 Agent 与 3 个 Skill 完成 React 18 代码库到 React 19 的体系化升级。读完本文,你将掌握从代码审计、依赖升级、源码迁移到测试修复的完整四阶段迁移管线,并了解 React 19 中所有破坏性变更与可选现代化改造的具体落地写法。

插件概览:专为 React 18 → 19 设计的迁移编排

react19-upgrade 是一个面向企业级代码库的 React 19 迁移工具包,核心思路是"专业分工 + 门禁把关":不依赖单一 Agent 一次性处理所有问题,而是将迁移拆解为 审计(Audit)→ 依赖(Deps)→ 源码迁移(Migrate)→ 测试(Tests) 四个阶段,每个阶段由专门的 Agent 负责,并由主协调器 react19-commander 在阶段之间设置验证门禁(Gate),确认通过后才允许进入下一阶段。

插件元数据定义在 plugins/react19-upgrade/plugin.json 中,其 extensions 区块声明了 5 个 Agent 文件与 3 个 Skill 目录:

  • Agents:react19-auditorreact19-commanderreact19-dep-surgeonreact19-migratorreact19-test-guardian
  • Skills:react19-concurrent-patternsreact19-source-patternsreact19-test-patterns

整体工作流在 agents/react19-commander.agent.md 中定义为严格的串行管线,明确"每次只调用一个子 Agent,禁止并行"。

安装与快速启动

在 GitHub Copilot 环境中通过以下命令安装该插件:

copilot plugin install react19-upgrade@awesome-copilot

安装完成后,直接向 Copilot 发起指令即可激活迁移:

Ask: "Start implementing React 19 migration for my codebase"

随后 react19-commander 会引导你依次完成:

  1. Audit → 识别全部破坏性变更与弃用模式;
  2. Deps → 升级到 react@19 及兼容库;
  3. Migrate → 修复所有弃用 API 与模式;
  4. Tests → 迁移测试套件并运行至全绿。

五大 Agent 分工详解

react19-commander:全管线主协调器

react19-commanderagents/react19-commander.agent.md)是整个迁移的"总指挥",拥有子 Agent 调度、终端执行、文件编辑、代码搜索与问题读取等工具权限,并通过 vscode/memory 工具实现跨会话的状态持久化。

内存协议(Memory Protocol) 是其可恢复性的关键:

# 每次会话开始先读取迁移状态
#tool:memory read repository "react19-migration-state"

# 每个门禁通过后写入状态
#tool:memory write repository "react19-migration-state" "[state JSON]"

状态对象采用如下结构:

{
  "phase": "audit|deps|migrate|tests|done",
  "auditComplete": true,
  "depsComplete": false,
  "migrateComplete": false,
  "testsComplete": false,
  "reactVersion": "19.x.x",
  "failedTests": 0,
  "lastRun": "ISO timestamp"
}

启动时,commander 先读取内存、再探测当前 React 版本:

node -e "console.log(require('./node_modules/react/package.json').version)" 2>/dev/null || cat package.json | grep '"react"'

随后向用户报告哪些阶段已完成、哪些待办,并从第一个未完成阶段继续——这意味着中途断线不会导致已完成的工作白做。

管线四阶段与门禁如下:

阶段 调用的子 Agent 门禁(Gate)条件
Phase 1 Audit react19-auditor .github/react19-audit.md 存在,且返回了问题总数
Phase 2 Deps react19-dep-surgeon 返回 GO,react@19.x.x 确认,npm ls 无 peer 错误
Phase 3 Migrate react19-migrator 源码(非测试文件)中弃用模式计数为 0
Phase 4 Tests react19-test-guardian 测试输出为 Tests: X passed 且 0 失败

Phase 4 通过后,commander 还会亲自执行最终验证门禁,运行构建与全量测试:

echo "=== FINAL BUILD ==="
npm run build 2>&1 | tail -20

echo "=== FINAL TEST RUN ==="
npm test -- --watchAll=false --passWithNoTests --forceExit 2>&1 | grep -E "Tests:|Test Suites:|FAIL|PASS" | tail -10

只有构建退出码为 0 且测试 0 失败才算 COMPLETE;若任一失败,commander 会定位是哪个阶段引入的回归,并携带具体错误上下文重新调用对应子 Agent。

交战规则同样值得留意:绝不跳过门禁(子 Agent 声称完成不算数,必须用命令验证)、绝不虚构完成状态、调用子 Agent 时始终传递完整上下文、善用内存实现会话恢复。迁移清单(Migration Checklist)完全由内存跟踪,涵盖从审计报告生成到构建成功的 20 余项检查点。

react19-auditor:只读不写的深度扫描器

react19-auditoragents/react19-auditor.agent.md)被设计为"外科手术式扫描器":读取一切、修复零文件,产出唯一的交付物是审计报告。它同样支持内存断点续扫(react19-audit-progress 键)。

扫描协议分四个阶段:

  • Phase 1 依赖审计:读取 package.json 中所有 react 相关依赖(react、testing、jest、apollo、emotion、router),并用 npm ls 排查 peer 冲突;
  • Phase 2 移除 API 扫描(必须修复):对 ReactDOM.renderReactDOM.hydrateunmountComponentAtNodefindDOMNodecreateFactoryreact-dom/test-utils 导入、Legacy Context(contextTypes/childContextTypes/getChildContext)、字符串 ref(this.refs.)逐项 grep;
  • Phase 3 弃用模式扫描(可选现代化):forwardRef、函数组件上的 defaultProps、无初始值的 useRef()propTypes 计数、无用的 import React from 'react'
  • Phase 4 测试文件扫描:错误位置的 act 导入、Simulate. 用法、react-test-renderer、以及 toHaveBeenCalledTimes 断言(StrictMode 调用次数可能需调整)。

扫描完成后,auditor 将结果写入 .github/react19-audit.md,报告按 🔴 Critical(破坏性)、🟡 Deprecated(应迁移)、🔵 Test-specific(测试相关)、ℹ️ Informational(无需改码)四类组织,并给出按优先级排序的 18 步迁移计划(先升依赖、再改源码、最后修测试)。值得注意的是,报告对 propTypes 与 StrictMode 行为变化做了专门说明:React 19 移除了内置的 propTypes 运行时校验,但 prop-types 包仍可独立工作;StrictMode 不再双调用 effect,因此依赖 ×2/×4 计数的 spy 断言需要实测更新。

react19-dep-surgeon:零冲突的依赖升级专家

react19-dep-surgeonagents/react19-dep-surgeon.agent.md)的目标是把依赖树升级到与 React 19 完全兼容且 0 peer 冲突。升级路径分六步:

  1. 升级 React 核心npm install --save react@^19.0.0 react-dom@^19.0.0,并用 node -e 确认两者版本均为 19.x.x,否则停止排查;
  2. 升级 Testing Library:安装 @testing-library/react@^16.0.0@testing-library/jest-dom@^6.0.0@testing-library/user-event@^14.0.0。理由很关键:RTL 14 及以下版本内部仍使用 ReactDOM.render,与 React 19 不兼容;
  3. 升级 Apollo Client(如存在):npm install @apollo/client@latest
  4. 升级 Emotion(如存在):npm install @emotion/react@latest @emotion/styled@latest
  5. 解决全部 peer 冲突:用 npm ls 定位违规包,逐一 npm install <package>@latest 复检。禁止使用 --force--legacy-peer-deps 仅作为最后手段使用,且必须在 package.json 的 _notes 字段中记录说明;若某包没有 React 19 兼容版本,则明确记录并上报 commander;
  6. 干净安装收尾:删除 node_modulespackage-lock.json 后重新 npm install,确认 npm ls 中的 WARN/ERR/peer 行数为 0。

最终输出 GO/NO-GO 决策:仅当 react@19.x.xreact-dom@19.x.x@testing-library/react@16.x 全部确认且 npm ls 无 peer 错误时才返回 GO。

react19-migrator:源码迁移引擎

react19-migratoragents/react19-migrator.agent.md)依据审计报告逐文件重写源码中的弃用与移除 API,绝不触碰测试文件,且逐文件写内存检查点以便中断续跑。其迁移参考(M1–M11)完整覆盖了 README 中列出的所有模式,其中最重要的几个:

M1 ReactDOM.rendercreateRoot

// Before
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));

// After
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);

M2 ReactDOM.hydratehydrateRootimport { hydrateRoot } from 'react-dom/client'; hydrateRoot(container, <App />)

M3 unmountComponentAtNoderoot.unmount():其中 rootcreateRoot(container) 的引用。

M4 findDOMNode → 直接 ref:函数组件用 useRef(null),类组件用 React.createRef(),统一通过 nodeRef.current 访问 DOM 节点。

M5 forwardRef → ref 作为直接 prop(可选现代化)

// Before
const Input = forwardRef(function Input({ label }, ref) {
  return <input ref={ref} />;
});

// After(React 19 新范式)
function Input({ label, ref }) {
  return <input ref={ref} />;
}

重要边界:forwardRef 在 React 19 中并未移除,属于可选改造而非强制。若组件契约依赖第二参数 ref 签名、或使用了 useImperativeHandle,保留 forwardRef 完全可行。这也与 auditor 的结论一致:forwardRef 只是"值得现代化",不是"必须修复"。

M6 函数组件 defaultProps → ES6 默认参数

// Before
function Button({ label, size, disabled }) { ... }
Button.defaultProps = { size: 'medium', disabled: false };

// After
function Button({ label, size = 'medium', disabled = false }) { ... }
// 彻底删除 Button.defaultProps 块

两条易错点:类组件不要迁移(defaultProps 在类组件上仍然有效);ES6 默认参数只在值为 undefined 时生效,不覆盖 null

M7 Legacy Context → createContextstatic contextTypes/childContextTypes/getChildContext() 替换为 const MyContext = React.createContext(defaultValue) + <MyContext value={...}> + static contextType = MyContext

M8 字符串 ref → createRefref="myInput" + this.refs.myInput 改为类字段 myInputRef = React.createRef() 并绑定 ref={this.myInputRef}

M9 useRef()useRef(null):所有无参数调用一律补上 null 初始值。

M10 propTypes 注释(不删代码):在每个 .propTypes = {} 上方添加说明注释,强调 React 19 不再运行时校验、保留仅为文档与 IDE 用途。

M11 清理无用的 import React from 'react':仅当文件不使用 React.xxx 前缀、不是类组件时才能移除。

migrator 的执行规则包含一条对并发模式的安全红线:绝不改动 useTransitionuseDeferredValueSuspensestartTransition 等并发逻辑——迁移只应触碰 React API 表面(forwardRef、defaultProps 等),并完整保留 Emotion css/styled 调用、Apollo hooks 与全部注释。完成验证通过一组 grep 命令确认弃用模式计数为 0。

react19-test-guardian:跑不绿不罢休的测试修复器

react19-test-guardianagents/react19-test-guardian.agent.md)负责把测试套件迁移到 React 19 兼容状态并运行至 0 失败。它的底线是:不跳过测试、不删除测试、不压制错误——如果某个测试连续 3 次修复失败,就写入审计报告的 "Blocked Tests" 区块并上报 commander。

其测试迁移参考(T1–T8)覆盖了测试侧的完整变化:

  • T1 act 导入修复act 不再从 react-dom/test-utils 导出,改为 import { act } from 'react'
  • T2 SimulatefireEventSimulate.click/change/submit/keyDown 全部替换为 @testing-library/reactfireEvent 对应方法;
  • T3 react-dom/test-utils 全量导出映射renderIntoDocument → RTL renderfindRenderedDOMComponentWithTag/scryRenderedDOMComponentsWithTag → RTL 查询(getByRolegetByTestIdgetAllByRole),isElementisCompositeComponent 等直接删除;
  • T4 StrictMode spy 调用次数更新:React 18 StrictMode 下 effect 双调用(spy 计数 ×2/×4),React 19 只调用一次(×1/×2)。策略是实测而非猜测——跑失败用例,从错误信息读取真实计数再更新断言;且注意渲染阶段(组件函数体)的调用在 React 19 StrictMode 下仍是双调用,计数保持 ×2;
  • T5 useRef 形状更新{ current: undefined }{ current: null }
  • T6 自定义 render helper 校验:确认测试工具函数用的是 RTL render 而非 ReactDOM.render
  • T7 错误边界测试更新:React 19 错误日志行为变化,console.error 从 React 18 的调用 2 次变为 1 次;
  • T8 异步 act() 包裹:对 "not wrapped in act(...)" 警告,用 await act(async () => { ... }) 包裹状态更新触发操作。

guardian 还内置了一张错误排查表,把常见失败与修法一一对应:

错误 原因 修复
act is not a function 导入位置错误 import { act } from 'react'
Simulate is not defined 导出已移除 替换为 fireEvent
Expected N received M StrictMode 调用次数变化 跑测试后用真实计数
Cannot find module react-dom/test-utils 包已被掏空 切换全部导入
cannot read .current of undefined useRef() 形状 null 初始值
not wrapped in act(...) 异步状态更新 包裹 await act(async () => {...})
Warning: ReactDOM.render is no longer supported 旧 render 残留在 setup 更新为 createRoot

执行循环为"按审计报告修一批 → 跑一次全量 → 逐个消灭 FAIL 文件"的迭代过程,直到 Tests: X passed 且无失败。

三大 Skill 配套

react19-concurrent-patterns:并发模式的"保留"与"采纳"

该 Skill(skills/react19-concurrent-patterns/SKILL.md)给出两条并行准则:

Part 1 保留:React 18 中已有的并发模式在迁移中绝不能被动摇——createRoot 正确写法、useTransition(React 19 中行为不变)、useDeferredValue(不变)、Suspense + React.lazy 代码分割(不变)都给出示例代码,并用 grep 校验迁移期间这些模式未被误改。

Part 2 采纳:迁移稳定后(而非迁移过程中)才值得引入的新 API——use() Hook、Actions 系列(useActionStateuseFormStatususeOptimistic)、以及用于数据获取的 Suspense 新模式,细节分别位于 skills/react19-concurrent-patterns/references/react19-use.mdskills/react19-concurrent-patterns/references/react19-actions.mdskills/react19-concurrent-patterns/references/react19-suspense.md

react19-source-patterns:源码迁移快速参考

该 Skill(skills/react19-source-patterns/SKILL.md)把全部源码侧迁移浓缩为一张速查表:ReactDOM.rendercreateRoot().render()ReactDOM.hydratehydrateRootunmountComponentAtNoderoot.unmount()findDOMNode → 直接 ref、forwardRef → ref 直接 prop、defaultProps → ES6 默认参数、useRef()useRef(null)、Legacy Context → createContext、字符串 ref → createRef()、无用 React 导入 → 移除。完整的前后对照代码(含 forwardRef + useImperativeHandledefaultProps 的 null/undefined 语义、跨文件的 Context Provider/Consumer 迁移等边界情况)在 skills/react19-source-patterns/references/api-migrations.md

react19-test-patterns:测试迁移优先级指南

该 Skill(skills/react19-test-patterns/SKILL.md)强调测试修复有严格依赖顺序:先修 act 导入(解锁一切)→ 再改 Simulate → 清理全部 test-utils 导入 → 实测 StrictMode 计数 → 处理剩余 act 警告 → 最后逐代码库验证一次自定义 render helper。其中给出了混合导入的拆分写法(import { act, Simulate, renderIntoDocument } from 'react-dom/test-utils' 拆成 react 与 RTL 两行导入)以及更完整的 test-utils API 映射表。

React 18 → 19 破坏性变更清单

以下是迁移必须面对的完整变更全景(与 auditor 扫描模式、migrator 修复模式一一对应):

已移除的 API(必须修复)

已移除 API 替代方案
ReactDOM.render() createRoot()
ReactDOM.hydrate() hydrateRoot()
ReactDOM.unmountComponentAtNode() root.unmount()
ReactDOM.findDOMNode() 直接 ref
React.createFactory() JSX
react-dom/test-utils 导出 act 移入 react,其余用 RTL 替代
Legacy Context API(contextTypes/childContextTypes/getChildContext createContext
字符串 ref(this.refs.x createRef

弃用但可用的模式(建议迁移)

  • forwardRef:ref 现在可作为直接 prop 传递,属可选现代化;
  • 函数组件上的 defaultProps:改用 ES6 默认参数;
  • 无初始值的 useRef():补 null

行为变化(影响测试断言)

  • StrictMode 不再双调用 effect(影响测试中的 spy 调用次数断言);
  • propTypes 运行时校验被移除(保留用于文档与 IDE,但不再产生运行时检查)。

迁移前置条件与升级路径

该插件假定目标代码库从 React 18 起步。如果你的项目还在 React 16/17,官方给出的路径是:先使用 react18-upgrade 插件(见 plugins/react18-upgrade/README.md)升级到 React 18.3.1,再使用本插件完成 React 19 的最终升级。这一前置条件也解释了为何整套管线严格围绕 React 18 → 19 的差异面设计——react@19 与 react-dom@19 的安装、RTL 16+ 的强制要求、createRoot 的既有正确性校验均以"已处于 React 18 生态"为前提。

关键特性总结

  • 覆盖 8 类以上已移除 React API 的系统性清理;
  • 处理复杂模式:Legacy Context、forwardRefdefaultProps、字符串 ref;
  • 基于内存的可恢复管线:中断后可无缝续跑,不重复已完成阶段;
  • 对不完整迁移零容忍:必须构建通过 + 测试全绿才宣告完成;
  • StrictMode 感知的测试修复(实测计数而非猜测);
  • Testing-library v16+ 兼容性验证;
  • 错误边界与异步测试模式更新。

该插件属于 awesome-copilot 社区仓库(MIT 许可),其完整定义可通过 插件元数据 与各 Agent/Skill 文档在仓库中进一步查阅。对正在规划 React 19 升级的团队而言,这套"审计 → 依赖 → 源码 → 测试"四阶段 + 门禁验证 + 内存续跑的组合,提供了一条可复制、可追踪、可验证的工程化迁移路径。

热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
34
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.15 K
2.77 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.36 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
929
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.94 K
1.03 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
534
603
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.47 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
398
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.05 K
529