mcpField
R
react-19-plugin-migration

react-19-plugin-migration

github.com/grafana开发2954.2k 次安装1 天前更新
代码仓库

关于 react-19-plugin-migration

帮助 Grafana 插件在不升级 React 的情况下做好 React 19 兼容准备,面向插件开发者,涵盖工具链、依赖、源码和 CI 调整。

主要功能

  1. 01扫描 React 19 兼容性问题
  2. 02更新 create-plugin 脚手架
  3. 03外置 JSX runtime
  4. 04升级 Grafana 与 React 类型依赖
  5. 05修复弃用的 React 写法并验证构建

适用场景

  1. 01为 Grafana 13 做插件准备
  2. 02查找插件源码中的不兼容 API
  3. 03更新构建和 lint 配置
  4. 04通过构建、类型检查和测试验证

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/grafana/skills --skill react-19-plugin-migration

安装后在 Claude Code 中输入/react-19-plugin-migration确认已加载。

附带文件references/known-issues.md

详细介绍

将 Grafana 插件迁移到 React 19

Grafana 13(2026 年 4 月)将从 React 18 迁移到 React 19。不兼容的插件将无法运行。 不要将 React 升级到 19——只进行向前兼容的更改。

所有更改都放在一个 PR 中。按顺序执行步骤。切勿手动编辑 yarn.lock。


步骤 1:检测插件上下文

PLUGIN_JSON=$([ -f src/plugin.json ] && echo "src/plugin.json" \
  || ([ -f plugin/src/plugin.json ] && echo "plugin/src/plugin.json" || echo ""))
PKG_JSON=$([ -f package.json ] && echo "package.json" \
  || ([ -f plugin/package.json ] && echo "plugin/package.json" || echo ""))
PLUGIN_ID=$(jq -r '.id' $PLUGIN_JSON 2>/dev/null)
[ -f yarn.lock ] && PM="yarn" || ([ -f pnpm-lock.yaml ] && PM="pnpm" || PM="npm")
CP_VERSION=$(jq -r '.version' .config/.cprc.json 2>/dev/null)
echo "PLUGIN_ID=$PLUGIN_ID  PM=$PM  CP=$CP_VERSION"

如果 PLUGIN_ID 为空,请向用户询问插件根目录路径。


步骤 2:扫描兼容性问题

构建插件并运行 React 19 兼容性扫描器:

npm run build 2>&1 | tail -5
npx -y @grafana/react-detect@latest 2>&1

保存输出。扫描器会标记:

  • jsxRuntimeImport / __SECRET_INTERNALS → 步骤 4 修复
  • defaultProps / propTypes / ReactDOM.render → 步骤 8(源代码修复)
  • findDOMNode → 步骤 6(依赖项升级)或步骤 8(源代码修复)

如果构建失败(插件此前从未构建过),请跳过此步骤,并在步骤 9 后运行 react-detect。如果输出显示“No breaking changes detected”,仍需继续——jsx-runtime 外部化和 grafanaDependency 升级始终是必需的。

步骤 9 后重新运行 react-detect,确认所有问题均已解决。


步骤 3:更新 @grafana/create-plugin

脚手架更新会引入 React 19 所需的 externals 提取、jest 模拟、Docker 修复和 webpack 改进。务必在 add externalize-jsx-runtime 之前完成此操作。

要求 Git 工作区干净。如果尚未创建功能分支,请先创建。

运行更新
npx @grafana/create-plugin@latest update 2>&1
如果 yarn install 因“engine is incompatible”而失败

更新过程会运行一个不带 --ignore-engines 的中间 yarn install。请手动完成:

yarn install --ignore-scripts --ignore-engines 2>&1 | tail -10

提交中间状态,然后重新运行:

git add -A && git commit -m "chore: intermediate create-plugin update" --no-verify
npx @grafana/create-plugin@latest update 2>&1
如果 ESLint 9 迁移(004)因解析器错误而失败

对于 ESLint 配置复杂的插件,自动迁移可能会生成无效的 JS。 不要跳过——提交已成功的更改,然后手动完成 ESLint 9 迁移:

git add -A && git commit -m "chore: update create-plugin (ESLint 9 migration manual)" --no-verify

然后按照下方的“完成 ESLint 9 迁移”部分完成操作。

更新后

务必运行安装并进行验证:

yarn install --ignore-scripts --ignore-engines 2>&1 | tail -10
cat .config/.cprc.json

如果有更改,请提交:

git add -A && git diff --cached --quiet || git commit -m "chore: update create-plugin scaffolding" --no-verify

步骤 3b:完成 ESLint 9 迁移

create-plugin update 会将 ESLint 升级到 v9,这需要使用扁平配置(eslint.config.js),而不是 .eslintrc。无论自动迁移(004)成功、部分成功还是失败,都必须确保 ESLint 正常工作后才能继续。

检查当前状态
ls eslint.config.js .eslintrc* .config/.eslintrc* 2>/dev/null
npx eslint --version 2>&1

有以下三种情况:

A)eslint.config.js 存在且 yarn lint 通过——自动迁移成功。继续下一步。

B)eslint.config.js 存在,但 yarn lint 失败——迁移不完整。请修复问题:

yarn lint 2>&1 | head -30

常见修复方法:

  • Invalid option '--ignore-path' 或 Invalid option '--ext' → 从 package.json 的 lint 脚本中移除这些标志。在 ESLint v9 扁平配置中,忽略项和文件匹配规则应在 eslint.config.js 中配置,而不是通过 CLI 标志配置。更新为:eslint --cache .
  • Cannot find module 'eslint-plugin-deprecation' → 从 eslint.config.js 中移除该导入/引用(已由 @typescript-eslint/no-deprecated 替代)
  • 其他无效的插件导入 → 如果对应的包已被移除,请从配置中删除这些导入

C)不存在 eslint.config.js——自动迁移失败。请手动创建:

ls node_modules/@grafana/eslint-config/flat.js 2>/dev/null

如果存在 flat.js,请以它为基础创建 eslint.config.js:

import grafanaConfig from '@grafana/eslint-config/flat';

export default [
  ...grafanaConfig,
  {
    ignores: ['**/dist/', '**/node_modules/', '**/.config/', '**/coverage/'],
  },
];

然后将旧 .eslintrc 中的自定义规则迁移到数组中的其他配置对象。 创建扁平配置后:

  1. 更新 lint 脚本:"lint": "eslint --cache ."
  2. 删除根目录下的 .eslintrc(保留 .config/.eslintrc——它由脚手架生成,不会造成问题)
验证 lint 是否正常工作
yarn lint 2>&1 | tail -20

使用 yarn lint --fix 修复可自动修复的问题。提交更改:

git add -A && git diff --cached --quiet || git commit -m "chore: complete ESLint 9 flat config migration" --no-verify

步骤 4:外置 jsx-runtime

始终使用 create-plugin add 命令。 要求 Git 工作树干净。

npx @grafana/create-plugin@latest add externalize-jsx-runtime 2>&1

验证:

grep "jsx-runtime" .config/bundler/externals.ts 2>/dev/null
  • 找到 → 提交并继续。
  • 未找到 → 命令失败。只有在这种情况下,才手动将 externals 添加到根目录的 webpack.config.ts:
externals: ['react/jsx-runtime', 'react/jsx-dev-runtime'],

提交:

git add -A && git diff --cached --quiet || git commit -m "feat: externalize jsx-runtime" --no-verify

步骤 5:升级 grafanaDependency

jq -r '.dependencies.grafanaDependency' $PLUGIN_JSON

如果尚未设为 >=12.3.0,请更新。步骤 3 中的 create-plugin add 可能已完成此操作。


步骤 6:升级依赖项

Faro(如果存在)
grep '"@grafana/faro' $PKG_JSON
PackageTarget
@grafana/faro-react^2.2.3
@grafana/faro-web-sdk^2.2.3
@grafana/faro-web-tracing^2.0.0
Grafana 包
grep '"@grafana/' $PKG_JSON | grep -v faro | grep -v create-plugin

将 @grafana/data、@grafana/runtime、@grafana/schema、@grafana/ui 升级到 ^12.2.0 或更高版本。 如果插件使用翻译,或 @grafana/scenes 有此要求,则添加 @grafana/i18n@^12.2.0。

React 类型

将 react 和 react-dom 升级到 ^18.3.0(尽早暴露 React 19 问题)。 如果缺少 @types/react@^18.3.0 和 @types/react-dom@^18.3.0,请将它们添加到 devDependencies。

移除已弃用的包

如果存在,请从 devDependencies 中移除:

  • eslint-plugin-deprecation(已由 @typescript-eslint/no-deprecated 替代)
  • @types/testing-library__jest-dom(已由 setupTests.d.ts 替代)
损坏的传递依赖项

如果 yarn install 因过时的 Git 引用而失败,不要编辑 yarn.lock。请添加 resolutions 条目:

"resolutions": {
  "<package-name>": "<working-version-or-git-ref>"
}

然后删除 yarn.lock 和 node_modules,再重新安装:

rm -rf node_modules yarn.lock
yarn install --ignore-engines 2>&1 | tail -10

步骤 7:修复未满足的 @openfeature/web-sdk 对等依赖

@grafana/runtime 依赖 @openfeature/react-sdk,后者将 @openfeature/web-sdk 作为 对等依赖。Yarn v1(classic)不会自动安装对等依赖。

检查插件是否使用 yarn classic:

yarn --version 2>&1 | head -1

如果版本以 1. 开头,请检查警告:

yarn install --ignore-engines 2>&1 | grep "unmet peer dependency.*openfeature/web-sdk"

如果发现警告:

yarn add -D @openfeature/web-sdk @openfeature/core --ignore-engines

跳过条件: Yarn v2+ 或 npm v7+(会自动安装对等依赖)。


步骤 8:修复源代码问题

grep -rn "ReactDOM\.render\|ReactDOM\.unmountComponentAtNode\|ReactDOM\.findDOMNode" src/ --include="*.tsx" --include="*.ts"
grep -rn "\.defaultProps\s*=" src/ --include="*.tsx" --include="*.ts"
grep -rn "\.propTypes\s*=" src/ --include="*.tsx" --include="*.ts"
grep -rn "contextTypes\|getChildContext" src/ --include="*.tsx" --include="*.ts"
grep -rn "createFactory" src/ --include="*.tsx" --include="*.ts"
grep -rn "ChangeEvent<HTMLInputElement>" src/ --include="*.tsx" --include="*.ts"
PatternFix
ReactDOM.render()createRoot(container).render(element)
函数组件上的 defaultProps移至解构参数默认值
类组件上的 defaultProps保留 — 仍然有效
propTypes移除
contextTypes / getChildContext使用 React.createContext() + useContext()
createFactory使用 JSX 或 createElement()
复选框上的 ChangeEvent<HTMLInputElement>改为 FormEvent<HTMLInputElement>

步骤 9:构建、类型检查、测试

rm -rf node_modules dist
yarn install --ignore-engines 2>&1 | tail -10
yarn build 2>&1 | tail -10
yarn typecheck 2>&1 | tail -10
yarn test --watchAll=false 2>&1 | tail -10
ErrorFix
Cannot find module 'react/jsx-runtime'未应用步骤 4 — 重新运行 create-plugin add
Cannot find module '@openfeature/web-sdk'步骤 7 — yarn add -D @openfeature/web-sdk @openfeature/core
Can't resolve '@grafana/i18n'yarn add @grafana/i18n@^12.2.0
Cannot read properties of undefined (reading 'ReactCurrentOwner')升级 @grafana-cloud/* 包 — 参见步骤 6
仅图标的 Button 缺少 aria-label添加 aria-label 属性(较新版 @grafana/ui 要求此属性)
yarn.lock 中的 Git 哈希过时在 package.json 中添加 resolutions,删除锁文件并重新安装

有关已知问题的详细信息(i18n 崩溃、@grafana/schema 类型中断、publicPath 不匹配),请参阅 references/known-issues.md。


步骤 10:更新 CI(如适用)

grep -rn "plugin-ci-workflows\|e2e-version" .github/workflows/ 2>/dev/null
  • plugin-ci-workflows@main 或 >= 6.0.0 → 已测试 React 19。无需更改。
  • plugin-actions/e2e-version → 添加 skip-grafana-react-19-preview-image: false。
  • 两者均未找到 → 使用 GRAFANA_VERSION=dev-preview-react19 docker compose up --build 手动测试。

步骤 11:压缩提交并推送

git reset --soft origin/main
git add -A
git commit -m "fix: Prepare plugin for React 19 compatibility"

提交消息正文应列出:create-plugin 版本变更、迁移到 ESLint 9、关键依赖项升级,以及任何源代码修复。


参考资料

评论

支持 Markdown