はじめに
ある React / TypeScript / vite の個人開発を一挙にアップグレードしようと思いました。
きっかけはnpm outdatedでほとんど更新が必要だったことと、一挙にアップグレードして対応する実験(経験蓄積)をしたかったためです。
個人開発だと誰の気兼ねなく自由に振る舞えるのでこういうときに便利です。
(当然ですが)本来一挙にアップデートないし、アップグレードなんてやるべきではないので注意してください。
一挙にアップグレードする手順
※くどいですが推奨されません。今回はあくまで個人開発での実験的作業です。
# npm-check-updates をグローバルインストール
npm install -g npm-check-updates
# 変更対象を確認
ncu
# package.json を更新
ncu -u
# 一挙にアップグレード
npm install
個別アップデート・アップグレードの手順
# 更新対象をチェック
npm outdated
# 個別にアップデート・アップグレード
#(※事前にドキュメントなどで更新による影響をチェックしておく)
#(※ライブラリによっては codemod など良しなにアップデート・アップグレードしてくれる機能を提供している場合もある)
npm install 対象ライブラリ名@latest
面倒くさいESLintv8からv9へのアップグレード及び移行
ご存知の方には釈迦に説法ですが、ESLintはv9からFlatConfigという破壊的変更が入っており、ただアップグレードするだけでなく、新たにeslint.config.mjs(js)を用意したり、そのファイルに適切な記述(設定)を行ったり、関連各種ライブラリのアップデートや新規インストールが必要になったりと、対応範囲が結構広いです。
v8からv9へのESLintのバージョンアップって、単純にアップデートするだけでなく、関連する無数の外部ライブラリのアップデートも発生します。
その外部ライブラリの中でも、v9に対応しているものとそうでないものがあったりするので、それに応じてライブラリのダウングレードを行う、もしくはアンインストールして代替ライブラリに変えるなどの対応も別途必要になります。
加えて今回は、Flat Config形式に移行しなければならないので、設定ファイルのコードの書き方も変更する必要があり、とてもコストを要する作業になることが予想できました。
とはいえ、ESLintを外して静的解析(コードを実行せずに行なう検証)を無くすのは良くないのでアップグレードします。
(前からBiomeが気になっていたので試しても良かったのですが、それはまた今度の機会に取っておきます)
アップグレードに際してふと、純粋にめんどくさかったこともあるのですが、 もしや ドキュメント読み込みや情報収集・整理を通じた移行作業なんて、まさしくLLMやAIエージェントが得意とするところでは? と思ったのです。
ただし、これまでAIを活用してきた経験上、すべてを丸投げすると中々思い通りにいかないケースも少なくなかったので、筆者の方で各種ライブラリをアップデート(アップグレード)しておいて作業環境を整えておきました。
Good to Know
ESLintv8 -> v9(FlatConfig)移行や設定を進める前に知っておくと良いことを紹介しておきます。
- 次の v10 では
FlatConfigしかサポートしない予定
旧来のeslintrc形式は完全に廃止されるため早めの移行推奨 - 適応する
ruleが重複した場合(filesプロパティでフィルタした後)配列の後ろのものが優先される
export default [
基本設定, // 優先度: 低
TypeScript設定, // 優先度: 中
個別ファイル設定 // 優先度: 高 ← これが適用される
]
-
FlatConfigは必ず1次元配列での単純な処理構造 -
override(設定上書き),extends(設定継承)の廃止
先述通りシンプルな配列ベースの上書き(後述優先ルール)仕様となる
// 旧: eslintrc
{
extends: [...], // ❌ 廃止
overrides: [...] // ❌ 廃止
}
// 新: FlatConfig
export default [
configA, // 直接配置
configB, // 直接配置
configC // 直接配置
]
- JavaScript標準のモジュール解決: ESLint独自の文字列ベース解決から、標準的なES Modulesのimportへ
- プラグイン指定
- v8(旧
config)まで
'@typescript-eslint' - v9 (
FlatConfig)
import typescript from '@typescript-eslint/eslint-plugin'
- v8(旧
- 設定継承
- v8(旧
config)まで
'plugin:react/recommended' - v9 (
FlatConfig)
...react.configs.recommended.rules
- v8(旧
- パーサー指定
- v8(旧
config)まで
'@typescript-eslint/parser' - v9 (
FlatConfig)
import parser from '@typescript-eslint/parser'
- v8(旧
- プラグイン指定
あとは頼んだ! Github Copilot
記事タイトル通り今回、Github Copilot(エージェントモード - 確か Claude 3.5 Sonnet)にESlint v8 -> v9 アップグレードと調整作業の全てを対応してもらいました。
作業においてGithub Copilotがいくつかエラーで詰まっていた箇所もあったので、他の人(チームメンバー)にも情報共有しやすいようマークダウンファイル(備忘録)も作成してもらいました。
処理結果
ESLint 関連
- インポートされたライブラリ
npm install --save-dev
@typescript-eslint/parser # TypeScriptパーサー
@typescript-eslint/eslint-plugin # TypeScript ESLintプラグイン
eslint-plugin-react # React用ESLintプラグイン
eslint-plugin-react-hooks # React Hooks用ルール
上記ライブラリをインストールして、以下のeslint.config.mjsをそのまま使えば、今回Github Copilotが調整してくれた静的解析を利用できます。
※2025/10追記:
Github Copilot調整コードをベースにClaude, ChatGPTの相互レビューでNext.js利用時の追加設定を加えた改良verが以下(eslint.config.mjsファイル)になります。
eslint.config.mjs
import typescript from "@typescript-eslint/eslint-plugin";
import typescriptParser from "@typescript-eslint/parser";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
/* --------------- /// Next.js利用時の追加設定 /// --------------- */
// [Next.js推奨用](https://nextjs.org/docs/app/api-reference/config/eslint#migrating-existing-config)のESLint設定
import js from '@eslint/js';
import { FlatCompat } from '@eslint/eslintrc';
const compat = new FlatCompat({
// import.meta.dirname is available after Node.js v20.11.0
baseDirectory: import.meta.dirname,
recommendedConfig: js.configs.recommended,
});
/* --------------- /// Next.js利用時の追加設定 /// --------------- */
/* ESLint設定 */
const eslintConfig = [
/* 除外するファイル/ディレクトリを指定 */
{
ignores: [
"next-env.d.ts", // Next.js が自動生成する環境定義ファイル
".next/**", // Next.jsのビルド出力ディレクトリ
"out/**", // Next.jsの静的エクスポートディレクトリ
"node_modules/**", // npmパッケージディレクトリ
"build/**", // ビルド成果物ディレクトリ
"dist/**" // 配布用ディレクトリ
]
},
/* --------------- /// Next.js利用時の追加設定 /// --------------- */
/* Next.js推奨設定(※ESLintの適用は後述優先なので総合設定よりも前に適用させておく)*/
...compat.config({
// extends: ['eslint:recommended', 'next'], // Next.js 14以前の推奨設定
extends: ['next/core-web-vitals'], // Next.js 14以降の推奨設定
}),
/* Next.js設定への追加ルール(※ESLintの適用は後述優先なので総合設定よりも前に適用させておく)*/
{
files: ["**/*.ts", "**/*.tsx"],
languageOptions: {
globals: {
React: 'readonly',
NodeJS: 'readonly',
},
},
plugins: {
"@typescript-eslint": typescript,
},
rules: {
"no-unused-vars": "off", // 通常のno-unused-varsを無効化
'no-irregular-whitespace': 'warn', // white-space(空白スペース)に関する警告
'no-undef': 'off', // TypeScriptがチェックするためoff
/* TypeScript ルール */
...typescript.configs.recommended.rules, // TypeScriptの推奨ルールセット
"@typescript-eslint/no-unused-vars": ["warn", {
ignoreRestSiblings: true, // 型定義内の変数を無視
args: "none" // 関数の引数をチェックしない(型注釈の重複を許容)
}],
},
},
/* --------------- /// Next.js利用時の追加設定 /// --------------- */
/* ESLint総合設定 */
{
// TypeScriptとTSXファイルに対する設定
files: ["**/*.ts", "**/*.tsx"],
// languageOptions: パーサーやその詳細なオプション設定、グローバル変数の定義、サポートするECMAScriptのバージョンなどを設定するプロパティ
languageOptions: {
parser: typescriptParser, // TypeScriptパーサーの設定
parserOptions: {
ecmaVersion: "latest", // 最新のECMAScript機能をサポート
sourceType: "module", // ESモジュール形式を使用
// より厳密な型チェック(型情報を必要とするルール)が必要な場合は以下を有効化
// project: "./tsconfig.json",
ecmaFeatures: {
jsx: true // JSX構文のサポートを有効化
}
}
},
// 使用するプラグインの設定
plugins: {
"@typescript-eslint": typescript, // TypeScript用のESLintプラグイン
react, // React用のESLintプラグイン
"react-hooks": reactHooks // React Hooks用のESLintプラグイン
},
// プラグインやフレームワークの追加設定
settings: {
react: {
version: "detect" // Reactのバージョンを自動検出(警告メッセージを防ぐため)
}
},
// 各種ルールの設定
rules: {
/* React ルール */
// ...react.configs.recommended.rules, // Reactの推奨ルールセット(`no-unused-vars`など他の設定と競合するため一旦コメントアウトで無効)
"react/jsx-uses-vars": "error", // JSX内での変数の使用状況を追跡(未使用変数の誤検知を防ぐ)
"react/prop-types": "off", // PropTypesの検証を無効化(TypeScriptで型チェックするため不要)
/* React Hooks ルール */
"react-hooks/rules-of-hooks": "error", // React Hooksのルールを厳格に適用(コンポーネントのトップレベルでのみ使用可能)
"react-hooks/exhaustive-deps": "warn", // useEffectなどの依存配列の検証(パフォーマンス最適化と副作用の適切な管理のため)
/* TypeScript ルール */
...typescript.configs.recommended.rules, // TypeScriptの推奨ルールセット
"@typescript-eslint/no-explicit-any": "warn", // any型の使用を警告(型安全性を維持するため)
"@typescript-eslint/explicit-function-return-type": "off", // 関数の戻り値型の明示を任意に設定(型推論で十分な場合が多いため)
"@typescript-eslint/no-unused-vars": ["warn", {
argsIgnorePattern: "^_", // アンダースコアで始まる引数は未使用でも警告しない(意図的な未使用を示す慣習)
varsIgnorePattern: "^_" // アンダースコアで始まる変数は未使用でも警告しない
}],
/* 一般的なコード品質ルール */
"no-console": ["warn", {
allow: ["warn", "error"] // console.logは警告、console.warnとconsole.errorは許可(本番環境での不要なログ出力を防ぐ)
}],
"prefer-const": "warn" // 再代入されない変数にはconstを推奨(意図しない再代入を防ぐ)
}
}
];
export default eslintConfig
生成当初はコメントが入っていなかったのですが希望すると丁寧に入れてくれました。
加えて、今回のアップグレードで不要(非推奨)となった.eslintrc.cjs(v8系まで使われていたファイル)や.eslintrc.jsonについても説明してくれて、削除までしてくれました。
強度としては必要最低限レベルで、環境や状況に応じて随時カスタマイズしていくベース設定のeslintという感じです。
この辺りのレビューは他の複数のAIに投げてレビューしてもらいました。
こういった点でもAIのお陰で作業効率や精度向上の恩恵を受けられている印象です。
さらには、未知への対応や言語習得などに関してもコメント付きで頼むとキャッチアップ効率が高まるので、(楽をする目的以外でも) そういった意味でもAIエージェントを活用するのは有益だと感じました。
ちなみに、蛇足ながらviteで初期セットアップ時(npm create vite@latest)に設定されているeslintは以下になります。
Viteで初期セットアップ時のESLint
eslint.config.js
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
export default tseslint.config(
// dist ディレクトリを ESLint のチェック対象から除外
{ ignores: ['dist'] },
{
// 基本設定の継承
// - JavaScript の推奨設定
// - TypeScript の推奨設定
extends: [js.configs.recommended, ...tseslint.configs.recommended],
// TypeScript ファイルを対象とする
files: ['**/*.{ts,tsx}'],
// 言語オプションの設定
languageOptions: {
// ECMAScript 2020 の機能を使用可能に
ecmaVersion: 2020,
// ブラウザのグローバル変数を使用可能に
globals: globals.browser,
},
// React 関連のプラグインを設定
plugins: {
// React Hooksのルールを適用するプラグイン
// - フックの依存配列チェック
// - フックの呼び出し順序の検証
'react-hooks': reactHooks,
// React Fast Refreshのサポート用プラグイン
// - 開発時のホットリロードを最適化
// - コンポーネントの状態を保持したまま更新可能
'react-refresh': reactRefresh,
},
// ルールの設定
rules: {
// React Hooks のルールを適用
...reactHooks.configs.recommended.rules,
// Fast Refresh 関連のルール設定
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true }, // 定数のエクスポートを許可
],
},
},
)
- (インストールされる)関連ライブラリ
- @eslint/js@9.27.0
- eslint-plugin-react-hooks@5.2.0
- eslint-plugin-react-refresh@0.4.20
- eslint@9.27.0
- globals@16.1.0
- typescript-eslint@8.32.1
作業履歴ドキュメント
ドキュメントはマークダウンファイルで生成してもらいました。
今回そんな予定はなかったものの、ものによっては生成したドキュメントを別のAIエージェントに投げて他の作業をしてもらうというユースケースもあるようなので、基本的にドキュメントはマークダウン形式で出してもらうようにしています。
今回の作業においてGithub Copilotが詰まったのは以下の部分になります。
-
必要なパッケージの不足
作業完了という報告を受けてnpm run lintすると全く動かない(設定エラーが出力されていた) -
TypeScript/Reactのパース設定の不足
上記対応をしてもらった上で再度npm run lintすると解析エラーが大量に出力される -
適切なルールセットの不足
1の対応と合わせて2と3を同時に解消(アップグレード及び調整作業の完了)
ドキュメントの内容(長いのでこちらに)
以下はGithub Copilotが生成した、ほぼ原文です(一部筆者で微調整)
発生していた問題と解決策
発生していた問題
- 必要なパッケージの不足
- TypeScript/Reactのパース設定の不足
- 適切なルールセットの不足
解決策のポイント
- 必要なパッケージを全てインストール
- TypeScriptとReactの両方に対応する包括的な設定を実装
- プロジェクトの特性に合わせた適切なルールセットを設定
インストール済みパッケージ
npm install --save-dev
@typescript-eslint/parser # TypeScriptパーサー
@typescript-eslint/eslint-plugin # TypeScript ESLintプラグイン
eslint-plugin-react # React用ESLintプラグイン
eslint-plugin-react-hooks # React Hooks用ルール
設定ファイル構造
eslint.config.mjs には以下の設定が含まれています:
インポート設定
import typescript from "@typescript-eslint/eslint-plugin";
import typescriptParser from "@typescript-eslint/parser";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
パーサー設定
- TypeScriptパーサーを使用
- ECMAScript最新バージョンをサポート
- モジュール形式のソースコード
- JSXサポートを有効化
プラグイン
- TypeScript (
@typescript-eslint) - React (
eslint-plugin-react) - React Hooks (
eslint-plugin-react-hooks)
適用ルール
TypeScriptルール
-
@typescript-eslint/no-explicit-any: any型の使用を警告 -
@typescript-eslint/explicit-function-return-type: 関数戻り値型の明示は任意 -
@typescript-eslint/no-unused-vars: 未使用変数を警告
Reactルール
-
react/jsx-uses-react: React使用の検知 -
react/jsx-uses-vars: JSX内の変数使用検知 -
react-hooks/rules-of-hooks: Hooksルールの強制 -
react-hooks/exhaustive-deps: 依存配列の検証(警告レベル)
プロジェクトでの使用方法
ESLintの実行
# 基本的な実行方法
npm run lint
# または直接 ESLint を実行
npx eslint . --ext .ts,.tsx
トラブルシューティング
エラーが発生した場合の一般的な解決手順:
- パッケージの再インストール
rm -rf node_modules
npm install
- ESLintの設定キャッシュのクリア
npm run lint -- --cache --fix
- TypeScriptの設定との整合性確認
-
tsconfig.jsonの設定がESLintの設定と矛盾していないことを確認
メンテナンス
定期的に以下を実施することを推奨します:
- パッケージの更新確認
npm outdated
- セキュリティ脆弱性のチェック
npm audit
- 新しいルールやベストプラクティスの確認と適用
今後の推奨事項
- 新しいTypeScriptやReact機能を使用する際は、ESLintの設定を適宜更新
- プロジェクトの要件に応じてルールの調整が必要な場合は、
rulesセクションを更新 - チーム開発の場合は、この設定をチームで共有し、一貫性のあるコーディング規約として活用
プロジェクト固有の注意点
-
コンポーネントの構造
-
src/components/以下の各機能ごとのディレクトリ構造に合わせたESLintルールを適用 - hooks、utils、tsディレクトリの規約を遵守
-
-
型チェック
-
tsconfig.jsonとの整合性を維持 - コンポーネント間のインターフェースの一貫性を確保
-
-
パフォーマンス最適化
- React Hooksのルール(特に依存配列)を適切に管理
- 不要なレンダリングを防ぐためのコード品質維持
最終更新日: 2025年5月21日
ドキュメントには、問題と解決策をはじめ、トラブルシューティングや今後のメンテナンス、推奨事項なども盛り込まれていました。
こちらで頼んではいないものの、AIが自律的に必要と判断した情報も記載されていて痒い所に手が届くものだと感心しました。
さいごに
今回、Github Copilotにほぼほぼ全て対応してもらったのですが、作業環境の構築を行った上で依頼した方がやはり効率的なように感じます。
あと、これは個人差があるかもですが途中で書いた通り、AIエージェントを利用することでキャッチアップ効率も高まる印象です。
しかし、すべてを任せきりにせず人間側でも事前に情報収集しておき、AIの自律的な作業の軌道修正が適宜行えるようにしておくのも重要だと感じました。
ここまで読んでいただき、ありがとうございました。
参考