ESLintをeslintrcからFlat Configに移行する際の最新手順 (2024年10月更新)

## 更新履歴

- 2024-10-17 最新状況を確認し、タイトルと本文を一部修正しました

## 記事を書くことにしたきっかけ

ESLintの設定ファイルのフォーマットが別物に変わろうとしています。
現在は過渡期となっており、ネットで調べていると古い情報もありました。

自分が移行した際にハマったポイントや、最初から知っておけたらよかったと思ったポイントをこの記事にまとめてみます。

## この記事を読む際の注意事項

状況は日々アップデートされています。
この記事の情報は古くなっていくと予想されますので、最終更新日と他の情報を照らし合わせながら読んでください。
(気が付いたら最新情報に更新していきたいと思っていますが、どうしても遅延はあると思います)

## 動作確認で使用したバージョン

- ESLint 9.9.0

## ESLintの設定ファイルのフォーマット

### これまで (ESLitnt 8系以前)

- 設定ファイル名: `.eslintrc.js` `.eslintrc.json` `.eslintrc.yml`
- 設定フォーマット名: `eslintrc`
- 呼び方: "eslintrc"や"Legacy"と呼ばれることが多い
- 公式ドキュメント: [Configuration Files (Deprecated)](https://eslint.org/docs/latest/use/configure/configuration-files-deprecated)

### これから (ESLitnt 9系以降)

- 設定ファイル名: `eslint.config.js` (CJSプロジェクトでESMで書く場合は.jsでなく.mjs)
- 設定フォーマット名: `Flat Config`
- 呼び方: 普通に"Flat Config"と呼ばれることが多い
- 公式ドキュメント: [Configuration Files](https://eslint.org/docs/latest/use/configure/configuration-files)

### 補足

- 8系でもv8.21.0(2022-08-01リリース)以降ならFlat Configが使用可能
- 10系でこれまでのeslintrcは削除予定

### 私個人の見解

- Cons
  - 後方互換がない思い切った変更をしたなあと感じています。
  - 対応は少し大変です (プラグインを作っている人も、プロジェクトに導入している人も)。
- Pros
  - ですが新しいFlat Configは扱いやすいフォーマットだとも思います。
  - 設定が楽かつ直感的になり、特に設定を複数ファイルに分割しているケースなどで扱いやすくなったと感じます。

## Flat Config以外に知っておいた方がいいこと

ESLint 9系にはFlat Config以外にも破壊的変更が含まれています。
例えば[Removed multiple context methods (公式ドキュメント)](https://eslint.org/docs/latest/use/migrate-to-9.0.0#-removed-multiple-context-methods)に記載があるように、いくつかのメソッドがリプレイスされました。

Flat Configへの移行だけを目的としてしまった私はかなりハマりました。
ESLint 8系で書かれていた記事を参考にしても9系では動かない可能性があるので注意が必要です。

実際に発生したことは後述の[eslint-plugin-react-hooks](#eslint-plugin-react-hooks)を参照してください (react-hooksのケースで書いていますが、他のプラグインでも流用できると思います)

## Flat Configへの移行手順

移行手順の全般に関する話題は既に凄くわかりやすくまとまっているので、以下を参照ください。

- 公式ドキュメント
  - [Configuration Migration Guide](https://eslint.org/docs/latest/use/configure/migration-guide)
- わかりやすかった日本語の記事
  - [ESLintのeslintrcをFlat Configに移行してみた (Zenn)](https://zenn.dev/keita_hino/articles/798bf62c6db663)
  - [ESLint を eslintrc から Flat Config に移行する、ハマりポイントを添えて。 (Qiita)](https://qiita.com/Shilaca/items/c494e4dc6b536a5231de)

## プラグイン側の対応状況

Flat Configへの移行に伴ってプラグイン側の対応が求められており、現在は順次対応が進んでいる状況です。

以下にプラグインの最新の対応状況がまとめられています。
[eslint/eslint Issue Tracking: Flat Config support #18093 (GitHub)](https://github.com/eslint/eslint/issues/18093)

2024年8月現在、Flat Configへの対応が進んできていますが、まだ未対応のプラグインも多くあります。
Flat Config未対応のプラグインをFlat Configで使用することは可能ですが、実際に作業してみると大変だったプラグインもありました。私が遭遇したケースを記載します。

### eslint-plugin-import

[eslint-plugin-import (npm)](https://www.npmjs.com/package/eslint-plugin-import)

~~import文をグループ順や辞書順などの任意の順序にするためのルールを提供してくれるプラグインです。~~
~~恐らく内部に名称が不一致となっている部分があるみたいで、他のプラグインのように移行することができませんでした。~~
~~[このIssueに書かれているコード](https://github.com/import-js/eslint-plugin-import/issues/2948#issuecomment-2148832701
)で対応することはできましたが、対応の複雑度が高めな印象です。~~
~~既に[対応PR](https://github.com/import-js/eslint-plugin-import/pull/3018)が出てきているので、そちらのマージを待ってみてもいいかもしれません。~~

(2024-10-17 追記) 
08/30にeslint-plugin-importのFlatConfig対応は完了となっています。上記は古い情報のため、取り消し線を引きました。

### eslint-plugin-react-hooks

[eslint-plugin-react-hooks (npm)](https://www.npmjs.com/package/eslint-plugin-react-hooks)

Reactのhooksに関するルールを提供してくれるプラグインです。
ちなみに[eslint-plugin-react (npm)](https://www.npmjs.com/package/eslint-plugin-react)の方はFlat Configの対応が完了していますが、hooksの方は2024年8月現在、完了していません。

こちらは以下の設定で動作します。

```js:eslint.config.js
import eslint from "@eslint/js";
import reactPlugin from "eslint-plugin-react";
import hooksPlugin from "eslint-plugin-react-hooks";

import { fixupPluginRules } from "@eslint/compat";

export default [
  // react-hooks以外の設定
  eslint.configs.recommended, 
  reactPlugin.configs.flat.recommended,

  // react-hooksの設定
  {
    plugins: {
      // ※ 調べているとfixupPluginRulesが書かれていない記述もありました。この点は後述します。
      "react-hooks": fixupPluginRules(hooksPlugin),
    },
    rules: {
      ...hooksPlugin.configs.recommended.rules,
    }
  }
]
```

(2024-10-17 追記) 
上記の状況は現在も継続しています。

## ESLint 8系と9系のFlat Config以外の違い

上記のeslint-plugin-react-hooksの設定例で`fixupPluginRules`を書かなかった場合は以下のエラーが発生します。

```bash:fixupPluginRulesが未記載の場合のエラー
$ yarn eslint
Oops! Something went wrong! :(

ESLint: 9.9.0

TypeError: context.getSource is not a function
Occurred while linting ${ファイル名}
Rule: "react-hooks/exhaustive-deps"
error Command failed with exit code 2.

(重要な行だけを抜粋しています)
```

私の場合、8系と9系の違いをわかっていない状態でこのエラーが発生してハマりました。

`fixupPluginRules`はESLint 9系の破壊的変更の影響を受けずに動作するようにしてくれるメソッドで、9系に対応していないプラグインの場合は使用が必須となっています。
今回の場合、`getSource`が新しいメソッドにリプレイスされていることがドキュメントから確認できます。
[Migrate to v9.x - Removed multiple context methods (公式ドキュメント)](https://eslint.org/docs/latest/use/migrate-to-9.0.0#-removed-multiple-context-methods)

### @eslint/compat

`fixupPluginRules`を提供しているnpmは以下です。`fixupPluginRules`以外にも提供されているメソッドがあります。
[fixupPluginRules (npm)](https://www.npmjs.com/package/@eslint/compat)

## VSCode extention側の対応状況

VSCodeを使用している場合、ESLint拡張を使用していることが多いと思います。
[VSCode ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)

以前は`"eslint.experimental.useFlatConfig": true`と設定しないとFlat Configが有効にならなかったようですが、3.0.5(2024-03-29リリース)以降では不要に変わっています。

## 最後に

移行のためのドキュメントだけでなく、移行ツールやサポートライブラリも充実していて、かなり手厚い状態になっていると感じました。コミュニティも活発に動いていて凄いライブラリとも改めて思いました。