react-19-plugin-migration について
React 自体はアップグレードせずに、Grafana プラグインを React 19 対応に備える手順ガイドです。プラグイン開発者向けに、ツール、依存関係、ソースコード、CI の変更を扱います。
主な機能
- 01React 19 の互換性問題をスキャン
- 02create-plugin の設定を更新
- 03JSX runtime を外部化
- 04Grafana と React 型依存関係を更新
- 05非推奨の React パターンを修正してビルド検証
活用シーン
- 01Grafana 13 に向けたプラグイン準備
- 02プラグインソース内の非互換 API の特定
- 03ビルドと lint 設定の更新
- 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 にアップグレードしないでください — 前方互換性のある変更のみを行います。
すべての変更を1 つの PRにまとめます。手順は順番どおりに実行してください。yarn.lock を手動で編集しないでください。
Step 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 が空の場合は、プラグインのルートパスをユーザーに尋ねてください。
Step 2: 互換性の問題をスキャンする
プラグインをビルドし、React 19 互換性スキャナーを実行します。
npm run build 2>&1 | tail -5
npx -y @grafana/react-detect@latest 2>&1
出力を保存してください。次の問題が検出されます。
jsxRuntimeImport/__SECRET_INTERNALS→ Step 4 で修正しますdefaultProps/propTypes/ReactDOM.render→ Step 8(ソースの修正)findDOMNode→ Step 6(依存関係の更新)または Step 8(ソースの修正)
ビルドが失敗した場合(プラグインがまだビルドされていない場合)は、この手順をスキップし、Step 9 の後に react-detect を実行します。出力が「No breaking changes detected」の場合も、作業を続けてください — jsx-runtime の外部化と grafanaDependency の更新は常に必要です。
Step 9 の後に react-detect を再実行し、すべての問題が解決したことを確認してください。
Step 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
Step 3b: ESLint 9 への移行を完了する
create-plugin update によって ESLint が v9 に更新されます。これに伴い、.eslintrc ではなくフラット設定(eslint.config.js)が必要になります。自動移行(004)が成功した場合も、一部成功した場合も、失敗した場合も、先に進む前に ESLint が動作することを確認してください。
現在の状態を確認する
ls eslint.config.js .eslintrc* .config/.eslintrc* 2>/dev/null
npx eslint --version 2>&1
次の 3 つのケースがあります。
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 のフラット設定では、除外対象とファイルの照合は CLI フラグではなくeslint.config.js内で設定します。次の内容に更新します: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 にあるカスタムルールを、配列内の追加の設定オブジェクトに移行します。
フラット設定を作成した後、次の作業を行います。
lintスクリプトを更新します:"lint": "eslint --cache ."- ルートの
.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
- 見つかった場合 → コミットして次へ進みます。
- 見つからない場合 → コマンドが失敗しています。その場合に限り、ルートの
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
| パッケージ | 目標 |
|---|---|
@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に置き換え)
壊れた推移的依存関係
古い git 参照が原因で yarn install が失敗する場合は、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/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"
| パターン | 修正 |
|---|---|
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
| エラー | 修正 |
|---|---|
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 is missing | 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:コミットをまとめて push する
git reset --soft origin/main
git add -A
git commit -m "fix: Prepare plugin for React 19 compatibility"
コミットメッセージの本文には、create-plugin のバージョン変更、ESLint 9 への移行、主要な依存関係の更新、およびソースコードの修正内容を記載してください。
参考資料
- 移行ガイド
- プラグイン開発者向け React 19 のブログ記事
- React 19 の変更履歴
- grafana-collector-app #1337 — create-plugin の更新とソース修正を含む、移行全体
- grafana/scenes のイシュー — 上流の i18n トラッキング