PrettierとESLintのコンフリクトの原因を理解する、解決する

12207 ワード

JavaScriptを書いていて保存を押しても一瞬修正されてすぐに戻ってしまう....こんな経験ありませんか?
gif
PrettierとESLintのフォーマッターがコンフリクトしている状態です🥺

今まで自分は起きるたびに色々いじってたらなんか直ってしまい、しばらくしてまた遭遇するということを繰り返し、毎回イライラしていました。

そこで、本記事では

  1. 【概念編】でなぜコンフリクトが起きるのかを理解する
  2. 【実践編】で実際に手を動かしてコンフリクトを再現し、解決する。

の流れでコンフリクトを完全理解していきます。

これを読めば今後PrettierとLinterのコンフリクトでイライラすることはなくなるでしょう!
ではいってみましょう!


【概念編】なぜコンフリクトが起きるのか

コーディングルールにおける2つのカテゴリ

PrettierやESLintの話にいく前にコーディングルールの2つのカテゴリについて理解しておく必要があります。
コーディングルールはスタイルに関するルール(Stylistic Rules)コードの品質に関するルール(Code-quality Rules) の2つのカテゴリに分けることができます。

7

スタイルに関するルールとは、プログラムの実行結果に直接影響しない書き方(スタイル)のルールです。 行の最大長(max-len)やスペースorタブ(no-mixed-spaces-and-tabs)などが挙げられます。

例) スペースを使うかタブを使うか

  console.log("hello")
	console.log("hello")

コードの品質に関するルールとはプログラムに直接影響し、バグを引き起こす可能性が高い書き方を取り締まるルールです。
例) ESLintの no-implicit-globals:

/*eslint no-implicit-globals: "error"*/
var foo = 1;
function bar() {}

Prettierの責務

この2つのコーディングルールの中で Prettierはスタイルに関するルール(Stylistic Rules)のみ を担当します。コードの品質に関するルールについてはノータッチです。
1

Linterの責務とコンフリクトが起きる原因

一方、ESLintを始めとする Linterはコードの品質に関するルールに加えてスタイルに関するルールも定義されている場合が多いです。

結果それぞれで定義されているスタイルに関するルールがコンフリクトしてしまいます。
これがPrettierとLinterでルールがコンフリクトしてしまう根本的な原因です。
2


【実践編】コンフリクトを起こして解決してみる

概念編でなぜコンフリクトが起きるのか理解できたので、今度は実際に手を動かしてコンフリクトを再現→解決してみます。

事前にprettiereslintのVSCodeの拡張をインストールして、空のプロジェクトを作成しておいてください。

$ mkdir eslint-prettier
$ cd eslint-prettier
$ yarn init

コンフリクトを再現させてみる

Prettierを導入する

  1. .vscode/settings.json を作成します。
.vscode/settings.json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true
}
  1. .prettierrc を作成します。
.prettierrc
{
  "semi": true
}

これだけでPrettierは導入は完了です。
試しに以下のようなindex.jsを作ってみて、保存時にコードが整形されることを確認してみてください。

index.js
console.log();console.log()

↓ 整形されてこうなるはず

index.js
console.log();
console.log();

ESLintを導入する

続いてESLintを導入します。

  1. インストール
$ yarn add eslint --dev
  1. .eslintrc.jsonファイルを作成
.eslintrc.json
{
  "rules": {
    "semi": ["error", "never"]
  }
}
  1. .vscode/settings.json に保存時にeslintのfixが走るように設定します。
.vscode/settings.json
{
  ...
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

はい!これでコンフリクトが起きました!
(普段は起きるとイライラするが、今回は起こしたかったので嬉しい笑)

gif2


コンフリクトを解決する

コンフリクトが再現できたので、解決していきます。

概念編で学んだように、ESLintがPrettierの範囲にまで侵食していることが根本的な原因なので、以下のように責務をキレイに切り分けられた状態にできると良さそうです。
3

これを実現するのが、eslint-config-prettierです。

eslint-config-prettierはESLintに含まれるスタイルに関するルールをoffにしてPrettierとルールが競合しないようにします。
結果として、責務がキレイに分割されます。

実際にやってみましょう。

  1. インストール
$ yarn add -D eslint-config-prettier
  1. .eslintrc.jsonにprettierを追加し、スタイルに関するルールを全てオフにします。この時rulesはextendsを上書きしてしまうため競合するrulesは全て削除します。
.eslintrc.json
{
+ "extends": ["prettier"],
- "rules": {
-  "semi": ["error", "never"]
- }
}

見事にコンフリクトが解消しました!
8


まとめ

スタイルに関するルールはPrettier、コードの品質に関するルールはESLintとして責務をキレイに切り分けることで、快適なフォーマットライフが過ごせそうです。

4

チームで開発する場合は

  • .prettierrc(スタイルに関するルール)
  • .eslintrc(コードの品質に関するルール)
  • .vscode/settings.json(拡張機能の設定)

の3ファイルをGithubで管理すると、ローカルの環境によって挙動が変わることがなくなりイライラする人が減るでしょう!

参考
Prettier vs. Linters
Integrating with Linters