ESLint と Prettier の使い分け
ESLint と Prettier は多くのプロジェクトで併用されるが、ツールの違いや使い分けが少しわかりづらいので、改めて調べて整理する。
前提知識
ESLint はいわゆる Linter と呼ばれるツール (公式サイト)
Prettier はいわゆる Formatter と呼ばれるツール(公式サイト)
Linter とは
プログラムコードを解析して指定したルールに沿ってコーディングが行われているか、バグに繋がりそうなコードはないかなどをチェックするツール。コードの品質を担保するために使用する。
Formatter とは
プログラムコードの自動整形を行うツール。インデントの付け方、行の折り返しなどを一定のルールに沿って自動で整形する。コードの一貫性や可読性向上のために使用する。
棲み分けがわかりにくいと感じる理由
例えば Linter であるESLint で適用することのできるルールには コード品質に関するものだけではなく、フォーマットに関するルールも存在 している。
さらに、提供されるCLIコマンドには検知に加えて自動で修正を行ってくれるオプションも存在しているため整形の機能もあると言える。
従ってPrettierと少し役割が被っていることが、両者のツールの違いや棲み分けがわかりづらいと感じる理由に感じた。
ただし、Linter はあくまで検知することに特化したツールであり整形を専門としたツールではない。
ESLint のルール例
コード品質に関するルール
例)no-unused-vars
エラーになる例
var x; // 使われていない変数定義に対してエラーを出す
var y = 10;
console.log(y);
エラーにならない例
var x;
console.log(x);
var y = 10;
console.log(y);
フォーマットに関するルール
例)max-len
エラーになる例
/*eslint max-len: ["error", { "code": 80 }]*/
// 一行の長さが指定した文字数以上だとエラーになる
var foo = { "bar": "This is a bar.", "baz": { "qux": "This is a qux" }, "difficult": "to read" };
エラーにならない例
var foo = {
"bar": "This is a bar.",
"baz": { "qux": "This is a qux" },
"easier": "to read"
};
ESLint と Prettier で被っているルールの例
ESLint と Prettier で被っているルールとしては例えば以下のようなものがある。
以下はどちらも statement(文)の最後に ;
をつけるかどうかに関するルール。
ESLint
- ルール名:semi 🔗
- ルールの内容:Require or disallow semicolons instead of ASI
// .eslintrc.json
{
"rules": {
"semi": ["error", "always"],
}
}
Prettier
- ルール名:Semicolons 🔗
- ルールの内容:Print semicolons at the ends of statements
// .prettierrc.json
{
"semi": true
}
ESLint と Prettier の棲み分け
ここまでみてきたように、ESLint自身でコードの書式(フォーマット)に関することを検知し修正することもできるが、コードの整形については Prettierの方が専門性があるので、公式ドキュメントにもあるように以下のように使い分けるのがよい。
- コードの書式(フォーマット)に関すること … Prettier
- コードの品質に関すること … ESLint
Use Prettier for code formatting concerns, and linters for code-quality concerns
https://prettier.io/docs/en/integrating-with-linters
ESLint と Prettierでルールがコンフリクトする可能性がある
ESLint と Prettierで役割を棲み分けようとしたとしても、ESLint と Prettier には同じ内容のルールが存在しているため、両方のツールを一緒に使うときにルールがコンフリクトしてしまう可能性がある。
コンフリクトする例
;
に関するルールを ESLint / Prettier それぞれで適用していたとする
Prettier
Prettier では 文の最後に ;
をつけないというルールを適用
// .prettierrc.json
{
"semi": false
}
ESLint
ESLint では文の最後に ;
をつける(ついていないとエラーを出す)というルールを適用
// .eslintrc.json
{
"rules": {
"semi": ["error", "always"]
}
}
;
がない状態に整形される
Prettier を実行すると // index.js
console.log("Hello World!");
$ npx prettier --write ./src/index.js
以下のように ;
が削除された状態で出力される
// index.js
console.log("Hello World!")
;
がない状態ではエラーになる
ESLint を実行すると // index.js
console.log("Hello World!")
$ npx eslint ./src/index.js
このように ESLint と Prettier を併用するとそれぞれで違うことをいってる!!という状態になってしまう可能性がある🥲
ルールのコンフリクトを防ぐ仕組み
そうしたことが発生しないように、ESLintのルールとPrettierで被っているルールについて、ESLint側でルールをオフにすることのできる仕組みが用意されている。
これを利用することで、コードの書式に関することは基本的にPrettierに寄せることができるようになる。
eslint-config-prettier
https://github.com/prettier/eslint-config-prettier
( 具体的にオフになるルールはこちら )
このパッケージをインストールし、 .eslintrc.*
の extends
フィールドを設定してあげることで、ESLint と Prettier 両者に存在しているルールをESLint側でオフにすることができる。
※ ただし、オフにできるのはextends
で有効になっているルールが対象で、 rules
フィールドの中で設定されているものはオフにならない。
{
"extends": [
"some-other-config-you-use",
"prettier" // some-other-config-you-use に入っているルールに対してPrettierとかぶっているものを無効化する
],
"rules": {
"indent": "error" // rulesの中身には触れない
}
}
例
"eslint:recommended"
に含まれているルールの中で no-extra-semi
というルールは Prettierにも存在するルールなので、これを例に見てみる。(参照)
検査対象のファイル
以下のように ;
が2つ付けられているコードを検査対象とする。
// index.json
var foo = 1;;
extends で prettier を指定しない時
以下のように設定した上で、eslint を実行すると、"eslint:recommended"
には"no-extra-semi": "error"
のルールが含まれているため、エラーが発生する。
// .eslintrc.json
{
"extends": [
"eslint:recommended"
]
}
extends で prettier を指定する時
eslint-config-prettier
をインストールした上で extends
に prettier
を指定すると、Prettier にも存在している"no-extra-semi"
のルールは無効になるため、eslintを実行してもエラーにはならない。
// .eslintrc.json
{
"extends": [
"eslint:recommended",
"prettier"
]
}
rulesにも設定がある場合
ただし、以下のように rules
フィールドで no-extra-semi
に関するルールを設定していた場合はそのルールが適用されてしまい、エラーが発生する。
{
"extends": [
"eslint:recommended",
"prettier"
],
"rules": {
"no-extra-semi": ["error"]
}
}
コンフリクトを検知する便利ツール
そうしたときに、prettier が提供してくれている eslint-config-prettier
というコマンドを使うことでコンフリクトするルールを検知することができる
npx eslint-config-prettier path/to/main.js
先ほどの設定の状態でコマンドを実行すると以下のようにコンフリクトしているルールを教えてくれる
結論
- ESLint と Prettier は以下のように使い分けるのがよい
- ESLint:コードの品質に関すること
- Prettier:コードの書式(フォーマット)に関すること
- ESLint と Prettier で設定するルールがコンフリクトする可能性があるので、被っているルールをESLint側でルールをオフにできる仕組みを一緒に導入するのが良い
Discussion