🐡

ESLintとPrettierの競合解決: 実践的トラブルシューティング

2024/07/11に公開

はじめに

この記事では、既存のJavaScriptプロジェクトでESLintPrettierを併用する際に遭遇した問題と、その解決までの道のりを共有します。この経験を通じて、単に「動くからOK」ではなく、なぜそう動作するのかを理解することの重要性についてを共有します。

Node.jsnpm、基本的なターミナルコマンドを叩く等の知識が必須になります。また、Pettierをすでに導入しているか、MarkuplintStylelintを導入したことがある方にとっては読みやすい内容になるかと思います。

とくに私は、linterの導入には、意外と言語が辿った歴史や背景を把握していると状況を飲み込みやすい傾向にあると考えています。

ご参考になれば幸いです。

背景:

基礎学習のために、かねてよりコードの一貫性を保つPrettierを使用していました。次のステップとしてES6以降のコードを学ぼうと考えましたが、意識的に書くのは難しいし、丸暗記なんてもってのほかです…。
そう考えてESLintを追加しようと思い立ったのですが、ここから「競合する設定の沼」に足を踏み入れることになりました。

問題の発見

はじめてのESLintを導入後、以下の問題に直面しました:

  1. ESLintPrettierのルールが競合し、保存時に期待通りのフォーマットが適用されない
  2. VSCodeでの自動修正が正しく機能しない
  3. コマンドラインでのリントチェックと、エディターでの表示が一致しない

トラブルシューティングの旅

1. エラーメッセージから学ぶ

実行コマンド:

npx eslint .
npx prettier --check .

最初に遭遇したのは、以下のエラーメッセージでした:

ESLint: 9.6.0
ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

このメッセージを見て、「ESLintのバージョンは9.6.0なのに、なぜ設定ファイルが見つからないんだろうか?」と疑問が生まれました。
ここでひとつの推測を立てます:ESLint v9から設定ファイルの形式が変わっているのではないか、と。

2. 設定ファイルの進化を理解する

調査の結果、ESLint v9からは.eslintrc.jsではなくeslint.config.jsが推奨されていることが分かりました。この発見により、設定ファイルを新しい形式に移行することにしました。

参考文献

ESLint Configuration Files

変更前(.eslintrc.js):

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  extends: ['eslint:recommended', 'plugin:prettier/recommended'],
  // ... その他の設定
};

変更後(eslint.config.js):

const js = require('@eslint/js');
const prettier = require('eslint-config-prettier');

module.exports = [
  js.configs.recommended,
  {
    files: ['**/*.js'],
    languageOptions: {
      ecmaVersion: 2021,
      sourceType: 'module',
    },
    // ... その他の設定
  },
  prettier,
];

配列にするメリットは優先順位を明確にして、異なる設定ソースを簡単に組み合わせることができること、
その上、順序によって優先順位を制御できるため、直感的に競合関係を把握しやすくなることでしょうか。

この設定方法は、なかなかおもしろい仕組みだと感じました。

3. PettierとESLintの協調

次の課題は、PrettierESLintを協調させることでした。eslint-config-prettierを使用し、Prettierの設定をESLintの設定配列の最後に配置することで、両者が競合せずに動作するようになりました。

4. VS Code設定の重要性

エディターの設定が思いのほか重要だということも学びました。とくに、以下の設定がキーポイントでした:

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "never"
  }
}

この設定により、保存時にPrettierが優先して実行され、ESLintとの競合を防ぐことができました。

5. 開発環境に応じた柔軟な対応

console.logの扱いについて悩んだ際、学習環境と本番環境でのニーズの違いを考慮することの重要性に気づきました。結果として、「警告レベル」に設定することで、デバッグの利便性と本番環境でのコード品質のバランスを取ることにしました。

私のような初学者は、挙動や出力のテストのためにコンソールを多用するはず…。でも、本番の開発環境では使用されることは少ない気がする…。
いろいろ考えた末に、使い終わった後はコメントアウトするなどの対応を取れるように一応「警告」として教えてくれる設定をすることにしました。

rules: {
  'no-console': 'warn',
  // ... 他のルール
}

6. 余談:VS Codeに事前定義スキーマ?!

VScodeを使っていると、TypeScriptを導入していなくても、たびたび型エラー警告を出されることがあります。
これはVScodeの中にデフォルトでTypeScriptの定義スキーマが組み込まれていることで、ある程度のテストがリアルタイムで行えるという仕組みのようです。

「実際のTypeScriptを導入したら、競合するんじゃ…?!」とも思いましたが、そうではないみたいでした。
むしろ、これらは協調してより精度の高い静的型チェックをリアルタイムで実現する基盤になっているようです。

今回の環境構築で、さまざまな発見のきっかけを作ってくれたのが、この型エラーでした。

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "never"
  }
}

"source.fixAll.eslint": "never"は、最初は"true"だったのですが、エラー警告のおかげで比較的早い段階で自分のミスに気づくこともできています。

学んだこと

  1. エラーメッセージの重要性: エラーメッセージを丁寧に読むことで、問題の本質を理解できることがあります。

  2. 設定ファイルの理解: ツールのバージョンアップに伴い、設定ファイルの形式や内容が変わることがあります。常に最新の情報をチェックすることが大切です。

  3. ツール間の連携: 複数のツールを使用する際は、それらの連携方法を深く理解することが重要です。

  4. エディター設定の影響: エディターの設定が開発環境全体に大きな影響を与えることを認識しました。

  5. 柔軟な対応: 開発環境と本番環境で異なる設定を使い分けるなど、状況に応じた柔軟な対応が必要です。

  6. 型エラーの有効活用:実行しなくても、事前にエラーを検知してくれるTypeScript特有の型システムがVScodeにも入っています!今すぐ活用すべきです!

まとめ

この経験を通じて、環境構築は単なる設定の羅列ではなく、各ツールの役割と相互作用を深く理解することが重要だと学びました。問題に直面したとき、「なぜ」を問い続け、公式ドキュメントやコミュニティの知見を活用することで、より堅牢で理解の深い開発環境を構築できることを実感しました。
今回の学びは、今後の開発プロジェクトでも大いに役立つはずです。皆さんも、環境構築で困ったときは、一歩立ち止まって考えてみてください。きっと新しい発見があるはずです。

Discussion