うわっ...私の.eslintrc、無駄が多すぎ...?
例えばこんな.eslintrc
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:react/recommended",
"prettier"
],
"plugins": [
"@typescript-eslint",
"react"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off"
}
}
最近ESLintの設定を見直すことがあったのですが、完全に上のような設定を書いていました。。
実は重複が多く、こんな感じで省略しても同じ設定になります。
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"prettier",
],
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off"
}
}
.eslintrcのextends設定
recommendedなどを使うときにextendsを使いますが、公式ドキュメントの説明はこうです。
A configuration file, once extended, can inherit all the traits of another configuration file (including rules, plugins, and language options) and modify all the options
簡単にいうと、あらかじめ用意されている設定を読み込んでおき、上書きで設定を追加・変更できるということです。冒頭の例ではこの5つをextendsに含めています。
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:react/recommended",
"prettier"
],
...
では実際はどのような設定をextendしているのか見てみましょう。
extends設定のソースコードの追い方
eslint:recommended
だけちょっと特殊なので最後に説明します。
plugin:
がついているもの
公式ドキュメントを要約すると
-
plugin:
の後にパッケージ名/設定名を指定する - パッケージ名は
eslint-plugin-
は省略した形で指定できる- (書いてないけど)
@
スコープがあるときは@スコープ/eslint-plugin
のeslint-plugin
は省略できる
- (書いてないけど)
{
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:react/recommended",
],
...
よって、ソースコードを探しに行く場合は以下のようになります。
extends | ソースコードがあるパッケージ |
---|---|
"plugin:@typescript-eslint/recommended" |
@typescript-eslint/eslint-plugin |
"plugin:react/recommended" |
eslint-plugin-react |
plugin:@typescript-eslint/recommended
、plugin:@typescript-eslint/eslint-recommended
の設定
GitHubにソースコードがありました。ここに recommended
と eslint-recommended
の設定がありそうです。
ようやくrecommend設定を見つけることができました。よく見ると設定の中でさらにextendsしています。
...
export = {
extends: ['./configs/base', './configs/eslint-recommended'],
rules: {
...
./configs/baseはこうなっていました。
export = {
parser: '@typescript-eslint/parser',
parserOptions: { sourceType: 'module' },
plugins: ['@typescript-eslint'],
};
そうです!ここでparser,parserOptions,pluginsの設定がしてあります!
ということは冒頭の例では書かなくてもextendsによってすでに設定されているものがあるので、削除することができます。
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended", // ここに設定されている
"plugin:@typescript-eslint/eslint-recommended",
"plugin:react/recommended",
"prettier"
],
"plugins": [
- "@typescript-eslint",
"react"
],
- "parser": "@typescript-eslint/parser",
"parserOptions": {
- "sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off"
}
}
さらにrecommend設定の中で './configs/eslint-recommended'
もextendsしており、追ってみると plugin:@typescript-eslint/eslint-recommended
と同じ設定を見ていました!ということで plugin:@typescript-eslint/eslint-recommended
も削除することができます。
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended", // ここに設定されている
- "plugin:@typescript-eslint/eslint-recommended",
"plugin:react/recommended",
"prettier"
],
"plugins": [
"react"
],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off"
}
}
plugin:@typescript-eslint/react
の設定
同様に、eslint-plugin-react
のソースコードはこちらにありました。
そしてrecommend設定を見てみると、
module.exports = {
...
configs: {
recommended: {
plugins: [
'react'
],
parserOptions: {
ecmaFeatures: {
jsx: true
}
},
rules: {
...
ここにもplugins,parserOptions設定がありました!
ということで重複している設定は削除できます。
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended", // ここに設定されている
"prettier"
],
- "plugins": [
- "react"
- ],
- "parserOptions": {
- "ecmaFeatures": {
- "jsx": true
- }
- },
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off"
}
}
plugin:
がついていないもの
公式ドキュメントを要約すると
- パッケージ名を指定する
- ただしパッケージ名から
eslint-config-
は省略した形で指定できる- (書いてないけど)
@
スコープがあるときは@スコープ/eslint-config
のeslint-config
は省略できる
- (書いてないけど)
{
"extends": [
"prettier"
],
...
よって、 ソースコードを探しに行く場合は以下のようになります。
extends | ソースコードがあるパッケージ |
---|---|
"prettier" |
eslint-config-prettier |
ありました。
index.tsを見てみたところrule設定のみで、ruleの内容も冒頭の設定とは重複はありませんでした。
eslint:recommended
eslint:
プレフィックスのものは特殊で、ソースコードとしてはこのあたりで.eslintrcのextends設定を読んでいますが、ファイルとしてはeslint/eslintのconf/eslint-recommended.js
を設定しています。
最終的にはこのような設定
重複を取り除くとこのような設定になりました。
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"prettier"
],
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off"
}
}
このようにすっきりしましたが、重複していても問題はないのでわかりやすさのために書いておくのもありかと思います。ただ知っておくことに損はないと思いましたのでこの記事を書きました。
注意点としては、.eslintrcの設定は下に書くほど優先が高い(上書きされていく)ので、順番をミスって設定変わってしまったということがあるかもしれないのと、提供されている設定はアップデートにより変更されるため、変更に追従する必要があるということかなと思います。
もし間違いなどあれば指摘ください🙇♂️
ちなみにextendsとpluginsの違いはこの記事がとてもわかりやすかったです。ありがとうございました。
.eslintrcのenv設定についてもまとめてみたので、知りたい方はぜひ!
では快適なESLint生活を!
Discussion
「ルールの改善, 保守をする時に毎回それぞれのextendsを探るのは、骨が折れる作業になると思うため重複があってもルールを明示しておいた方が良く、無駄ではないのでは🤔」と思っていました。ですが、引用した背景を見つけて納得しました。記事の投稿、ありがとうございます。
コメントありがとうございます😄
ほんとにおっしゃる通りでextends探るのは大変なので、あえて明示しておくのも全然ありだと思います!
eslint-config-airbnbなども見ましたが、それぞれに切り出したファイルごとで重複しても書いていたりしますし、一概に省略するのが正しいとは全く思っておりません👍