ESLintのFlat Config対応 (2024) 公開日: 2024/12/03 最終更新日: 2024/12/03
以前、ESLintをFlat Configに置き換えるという記事を書きました。
eslintをflat configで書き換える | sunabox eslintの設定をflat configで置き換えてみました。 suna.dev
この記事を書いたのは2年前で、当時はまだ各種pluginやconfigのライブラリがFlat Configに対応していなかったため、各所でFlatCompatを使う必要がありました。
あれから2年の時が経ち、各種ライブラリがFlat Configをサポートしています。
また、最近Next.jsのv15によってeslintのv9対応がなされたこともあり、より最適な形でFlat Configとして移行できるようになったと思います。
こうした流れを受けて、最近プロダクトでESLintのFlat Config移行をしたのでその時に色々調べたことを備忘録として残しておきます。
基本的な設定の仕方などは以前の記事に記載したのとMigration Guideが用意されているので省略。
Configuration Migration Guide - ESLint - Pluggable JavaScript Linter A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
eslint.org
今回使用したpackageのバージョンは以下。
主な移行対象は@typescript-eslint
とeslint-config-next
です。
Info Icon eslint: 9.14.0
eslint-config-prettier: 9.1.0,
eslint-plugin-import: 2.31.0,
typescript-eslint: 8.16.0
eslint-plugin-react: 7.37.2,
eslint-plugin-react-hooks: 5.0.0,
@next/eslint-plugin-next: 15.0.3,
これまでは.eslintignore
にglobalにignoreしたいファイルを記載していました。
Flat Configではこれもオブジェクトとして設定します。
eslint.config.mjs export default [
{
ignores: [ "**/node_modules/**" , "**/dist/**" , "**/public/**" ],
},
...
];
注意点として、従来の.eslintignore
のようにglobalにignoreしたい意図で設定する場合は、そのオブジェクトの中ではignores
以外は設定してはいけません。
If ignores is used without any other keys in the configuration object, then the patterns act as global ignores.
https://eslint.org/docs/latest/use/configure/configuration-files#configuration-objects
ドキュメントにもしっかり書いてました。最初files
を併記していたせいでignores
が効かなくて若干ハマりました。
これまでは@typescript-eslint/parser
と@typescript-eslint/eslint-plugin
をそれぞれインストールし、extends
に以下のような設定を書くことでplugin, parser, rulesを一括で設定していました。
.eslintrc.json {
"extends" : [
"plugin:@typescript-eslint/recommended" ,
],
}
Flat Configでは新しくtypescript-eslint
を使用でき、config
関数を使用することが推奨されています。
eslint.config.mjs import tseslint from "typescript-eslint"
export default tseslint. config (
tseslint.configs.recommended,
{
...
}
)
これで同様にpluginとparser, rulesを一括で設定できます。
実際のプロジェクトでは全体の中の1つのオブジェクトとして設定されてるようにしたかったため、以下のように書き換えましたがこの辺は好みかと思います。
eslint.config.mjs import tseslint from "typescript-eslint"
export default [
... tseslint. config ({
extends: [tseslint.configs.recommended],
}),
{
...
}
]
ちなみにparserとpluginをそれぞれ個別に設定することもtypescript-eslint
だけで可能です。
そのため、@typescript-eslint/parser
と@typescript-eslint/eslint-plugin
はもはや不要になります。
eslint.config.mjs import tseslint from "typescript-eslint"
export default [
plugins: {
'@typescript-eslint' : tseslint.plugin,
},
languageOptions: {
parser: tseslint.parser,
},
...
]
ちなみにpluginを設定する場合、namespaceは以前と同じ@typescript-eslint
とすることが強く推奨されています。
We strongly recommend declaring our plugin with the namespace @typescript-eslint as shown above. If you use our shared configs this is the namespace that they use. This has been the standard namespace for our plugin for many years and is what users are most familiar with.
https://typescript-eslint.io/packages/typescript-eslint#advanced-usage
以前まではeslint-config-next
を使っていました。
.eslintrc.json {
"extends" : [
"next/core-web-vitals" ,
],
}
しかし、こちらは現時点ではまだFlat Config対応していません。
こちらのissueによるとFlatCompatを使う方法で解決できると記載されています。
New ESLint "flat" configuration file does not work with `next/core-web-vitals` · Issue #64114 · vercel/next.js Link to the code that reproduces this issue https://codesandbox.io/p/devbox/pensive-star-go8s7s To Reproduce Run npm run dev and observe the error showing that ...compat.extends("next/core-web-vita... github.com
試してみたところ、確かに動いたのですがいくつか点で微妙だなと思いました。
微妙な点その1: 内部で@typescript-eslint
をpluginとして定義している
Flat Configでは同じplugin定義を登録するとエラーになります。
next/core-web-vitals
の中で@typescript-eslint
をpluginとして定義しているため、その状態でtseslintの設定を行うとエラーになります。
eslint.config.mjs export default [
... compat. extends ( 'next/core-web-vitals' , 'next/typescript' ),
... tseslint. config ({
extends: [tseslint.configs.recommended],
}),
]
TypeError: Key "plugins": Cannot redefine plugin "@typescript-eslint".
そのため、回避しようとすると若干煩雑な記述をせざるを得ませんでした。
eslint.config.mjs export default [
... compat. extends ( 'next/core-web-vitals' , 'next/typescript' ),
... tseslint.configs.recommended. map (( conf ) => {
// next/core-web-vitalsの中でも@typescript-eslintをpluginに設定していて、二重定義でエラーになるためplugins以外を設定する
const { plugins: _, ... rest } = conf
return { ... rest }
}),
]
微妙な点その2: 内部でeslint-plugin-import
をpluginとして定義している
その1と類似しますが、eslint-plugin-import
も内部でpluginとして定義しているため、定義しようとすると同様にエラーになります。
これは単純に定義しないようにすればすれば回避できますが、pluginが暗黙的に設定されているという点でFlat Configの利点を活かしきれてないように思います。
微妙な点その3: Flat Configでしか使用できない機能が使用できない
後述するESLint Config InspectorはFlat Configだけで使用できる機能です。
eslint-config-next
を使用している場合は、Flat Config対応していないためこの機能が使用できませんでした。
以上の点から、FlatCompat
を使う方針は断念。
別のDiscussionで使用するpluginをそれぞれ個別に設定する方法が記載されていたのでこちらの方法を採用しました。
How to use new "flat config" approach in Eslint? · vercel/next.js · Discussion #49337 Summary I have Eslint working in a TypeScript Next.js project, but I want to switch to the new "flat config" approach that Eslint offers. (Why is that not Next.js's default?) I created /eslint.conf... github.com
eslint.config.mjs import nextPlugin from "@next/eslint-plugin-next"
import reactPlugin from "eslint-plugin-react"
import reactHooksPlugin from "eslint-plugin-react-hooks"
export default [
...
reactPlugin.configs.flat.recommended,
reactPlugin.configs.flat[ "jsx-runtime" ],
{
plugins: {
"react-hooks" : reactHooksPlugin,
"@next" : nextPlugin,
},
... reactHooksPlugin.configs.recommended.rules,
... nextPlugin.configs.recommended.rules,
... nextPlugin.configs[ "core-web-vitals" ].rules,
"@next/next/no-img-element" : "error" ,
"react/prop-types" : "off" ,
}
]
eslint-config-prettier
の中身はrules
の中にあらゆるruleがoff
で設定されているだけなので、ruleの最後に適用するだけでokです。
eslint.config.mjs import prettierConfig from "eslint-config-prettier"
export default [
...
{
rules: {
...
"react/prop-types" : "off" ,
... prettierConfig.rules,
}
}
]
Flat Configで使用できるツールとしてESLint Config Inspectorがあります。
Introducing ESLint Config Inspector - ESLint - Pluggable JavaScript Linter A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
eslint.org
eslint --inspect-config
を実行すると、設定されている内容を可視化したサーバーが立ち上がります。
わりと使い心地良いです。
ちなみに、linterOptions
とsしてdefaultでreportUnusedDisableDirectives: 1
が入っていて、未使用のdisableコメントをwarnにしてくれるようになってました。
このオプション自体は以前からあったらしいんですが、初めて知りました。
v8.56.0からerrorにもできるようになったらしいです。
こういうdefaultの設定も視覚的に見れるようになったのは便利だなと思います。
上記のConfig Inspectorはかなり便利ですが、Flat Configでしか使えません。
Flat Configに移行した前後で適用されるルールが変わっていないか、適用するファイルが変わっていないかをきちんとチェックしたいです。
以下の記事がとても参考になりました。
新卒エンジニアがESLintのFlat Config移行と格闘した話 - ドワンゴ教育サービス開発者ブログ ESLintのFlat Configへの移行は進んでますでしょうか?試してみたでしょうか? 今回はドワンゴの新卒エンジニアが初仕事として取り組んだ、ESLintのFlat Configへの移行に関して「その方法と嵌ったところの乗り越え方」をお伝えします。 この記事で言及すること Flat Configに書き変えるときに見る資料 ESLintのconfigをFlat Configに移行するとき、configs.recommendedなどのプリセットを用いる場合はFlatCompatを使う eslint-plugin-importを使用してると嵌る どうやって新旧configが同じになっていること… blog.nnn.dev
この記事を参考に、対象ファイルが変わってないかは以下のコマンドで確認しました。
pnpm eslint --debug "src/**/*.ts" | & grep "eslint:languages:js Parsing successful:" | sed 's/.*eslint:languages:js Parsing successful://'
適用されるルールが変わっていないかは以下のコマンドでファイル出力し、以前のファイルと比較して確認しました。
pnpm eslint --print-config src/foo.tsx > eslint-after.log.json
この辺をいい感じにチェックしてくれるツールもありますが、今回は使用しませんでした。
GitHub - sajikix/check-eslint-config-compat Contribute to sajikix/check-eslint-config-compat development by creating an account on GitHub. github.com
globalなignoreをしたいならignores
のみを設定したオブジェクトを定義する
@typescript-eslintのリプレイスはtypescript-eslint
を使う
eslint-config-nextはFlat Config対応していないので、pluginを個別に設定する
以前も移行作業自体はしたことがありますが、個人的には適用内容をとても追いやすくなったと思います。
可視化するESLint Config Inspectorも便利です。
以前よりもライブラリのサポートが進んでFlatCompat
を一切使わずにFlat Config移行することができました。
Configuration Migration Guide - ESLint - Pluggable JavaScript Linter A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
eslint.org
How to use new "flat config" approach in Eslint? · vercel/next.js · Discussion #49337 Summary I have Eslint working in a TypeScript Next.js project, but I want to switch to the new "flat config" approach that Eslint offers. (Why is that not Next.js's default?) I created /eslint.conf... github.com
新卒エンジニアがESLintのFlat Config移行と格闘した話 - ドワンゴ教育サービス開発者ブログ ESLintのFlat Configへの移行は進んでますでしょうか?試してみたでしょうか? 今回はドワンゴの新卒エンジニアが初仕事として取り組んだ、ESLintのFlat Configへの移行に関して「その方法と嵌ったところの乗り越え方」をお伝えします。 この記事で言及すること Flat Configに書き変えるときに見る資料 ESLintのconfigをFlat Configに移行するとき、configs.recommendedなどのプリセットを用いる場合はFlatCompatを使う eslint-plugin-importを使用してると嵌る どうやって新旧configが同じになっていること… blog.nnn.dev