Next.js 15でESLint 9 / Flat Configに移行する
Next.js 15でESLint 9のサポートが行われたので、このタイミングで移行を進める。
対象は個人のブログサイト↓
現在の.eslintrc.jsはこんな感じ
基本的な設定は @mh4gf/eslint-config
というパッケージにまとめ、そこから読み込む形としている
今回はこちらも合わせてFlat Config対応してしまいたい
ESLintのマイグレーションガイドを見てみる
破壊的変更の説明であり、マイグレーション手順があるわけではなさそう
適宜参照する形にする
まずpackage.jsonでバージョンを上げてみる
この状態で next lint
を実行
pnpm lint:next
> mysite@ lint:next /Users/mh4gf/ghq/github.com/MH4GF/mysite
> next lint
=============
WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.
You may find that it works just fine, or you may not.
SUPPORTED TYPESCRIPT VERSIONS: >=4.7.4 <5.5.0
YOUR TYPESCRIPT VERSION: 5.6.3
Please only submit bug reports when using the officially supported version.
=============
Error while loading rule '@typescript-eslint/naming-convention': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.
Occurred while linting /Users/mh4gf/ghq/github.com/MH4GF/mysite/app/(pages)/[slug]/_features/Content.tsx
ELIFECYCLE Command failed with exit code 1.
@typescript-eslintのパーサー周りでエラーになっている。
パースエラーは一旦置いておき、Flat Config移行をしてしまう
ESLintが提供するマイグレーションコマンドがあるとのことなので実行してみる
npx @eslint/migrate-config .eslintrc.js
Need to install the following packages:
@eslint/migrate-config@1.3.3
Ok to proceed? (y) y
Migrating .eslintrc.js
WARNING: This tool does not yet work great for .eslintrc.(js|cjs|mjs) files.
It will convert the evaluated output of our config file, not the source code.
Please review the output carefully to ensure it is correct.
Wrote new config to ./eslint.config.mjs
You will need to install the following packages to use the new config:
- @eslint/js
- @eslint/eslintrc
You can install them using the following command:
npm install @eslint/js @eslint/eslintrc -D
警告が出ており、JavaScriptによる設定ファイルの場合正しく動作しない可能性があるとのこと。式や文が含まれると難しいんだろうな。
生成されたファイルは以下 ぱっと見互換はありそうに見える
追加しろと言われたパッケージを追加
この時点でも@typescript-eslintのパーサーエラーは出てるが、ちょっとだけメッセージは変わったな
pnpm lint:next
> mysite@ lint:next /Users/mh4gf/ghq/github.com/MH4GF/mysite
> next lint
=============
WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.
You may find that it works just fine, or you may not.
SUPPORTED TYPESCRIPT VERSIONS: >=4.7.4 <5.5.0
YOUR TYPESCRIPT VERSION: 5.6.3
Please only submit bug reports when using the officially supported version.
=============
Error while loading rule '@typescript-eslint/await-thenable': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.
Note: detected a parser other than @typescript-eslint/parser. Make sure the parser is configured to forward "parserOptions.project" to @typescript-eslint/parser.
Occurred while linting /Users/mh4gf/ghq/github.com/MH4GF/mysite/app/(pages)/[slug]/_features/Content.tsx
ELIFECYCLE Command failed with exit code 1.
Flat Configのキャッチアップ
古い設定はFlatCompat
を使うことで互換性を保ちつつ利用できる。
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
ゴールはFlatCompatを消すところになりそうか
パッケージが分かれているとデバッグがややこしいので、一旦@mh4gf/eslint-configの内容をコピーしてくる
各プラグインのREADMEを読みつつ、Flat Configに置き換えていった
使っていたのは以下のプラグインで、それぞれFlat Configに対応していた
- typescript-eslint
- eslint-plugin-import
- eslint-plugin-unused-imports
これにより実行時エラーは出なくなったが、各ルールのエラーが出るように。これらはプラグインのアップデート漏れによるものかな。
typescript-eslintは 'plugin:@typescript-eslint/recommended-requiring-type-checking'
から tseslint.configs.recommendedTypeChecked
に変わったというのもあるので、含まれるルールが変わった可能性もあるかも。
pnpm lint:next
> mysite@ lint:next /Users/mh4gf/ghq/github.com/MH4GF/mysite
> next lint
./app/_components/ui/command.tsx
28:11 Error: An interface declaring no members is equivalent to its supertype. @typescript-eslint/no-empty-object-type
./app/_features/command/items/CommandLinkItem.tsx
19:5 Error: Expected an assignment or function call and instead saw an expression. @typescript-eslint/no-unused-expressions
./app/_features/command/items/SearchGroup.tsx
39:9 Warning: Unused eslint-disable directive (no problems were reported from 'import/no-unresolved').
./app/_features/markdownRenderer/elements/Paragraph.tsx
23:3 Error: Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 10 characters or longer. @typescript-eslint/ban-ts-comment
./app/_features/richLinkCard/__tests__/getOGP.test.ts
1:1 Warning: Unused eslint-disable directive (no problems were reported from 'import/no-unresolved').
./app/_features/viewTransition/isSameOrigin.ts
8:28 Error: Unexpected constant truthiness on the left-hand side of a `||` expression. no-constant-binary-expression
info - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules
ELIFECYCLE Command failed with exit code 1.
指摘は全て妥当な内容だったので、指摘の通り修正
無事next lintが通った!
pnpm lint:next
> mysite@ lint:next /Users/mh4gf/ghq/github.com/MH4GF/mysite
> next lint
✔ No ESLint warnings or errors
FlatCompatを消す作業
"eslint:recommended"
を js.configs.recommended
に
eslint-plugin-nextはFlat Configにまだ対応していないとのことなので、含まれているプラグインを直接明示する
参考:
これでFlatCompatが消えた!
@mh4gf/eslint-config をFlat Config対応する
プラグインのマイグレーションガイドを見ながらやっていく
最終的にはこんな感じになった
これは@mh4gf/eslint-config v0.6.1としてリリースされている
無事ESLint 9にアップグレードできました!
最終的なeslint.config.mjs