前言#
これは ESLint と他の関連ツールの優劣を比較する記事ではなく、私がコードチェックとフォーマットに ESLint を選んだ理由を紹介するものです。他のツールについて言及せざるを得ないこともありますが、私は人気のあるツールが存在するのは、それぞれに特徴と利点があるからだと思います。ユーザーとして、私たちは自分のニーズや好みに基づいて適切なツールを選べば良いのです。ツールに問題がある場合は、フィードバックや貢献を通じて改善を手助けできます。
私が重視する ESLint の利点#
より柔軟なフォーマット#
なぜPrettierやdprintのようなフォーマットツールを使用しないのかについて、Anthony Fu のWhy I don't use Prettierという記事が十分に明確に述べています。ここで、私の考えを少し補足します。
printWidth
を設定しても、Prettier にいつ改行したいかを伝えることはできません。printWidth
の値を増やして不適切に改行される長い文字列変数を回避しようとすると、期待通りに改行されるべき多引数関数の引数が正しく改行されない可能性があります。// prettier-ignore
の問題は// @ts-ignore
と同様で、ツールにここで改行しないように伝えることには成功しますが、同時にここで適用できる他のフォーマットルールを失ってしまいます。
Prettier の哲学は、ユーザーがフォーマットの設定オプションを考慮する必要がなく、コードを安心して美しくするために任せられることですが、実際には既存の設定オプションが Prettier が現在の js コミュニティで最も人気のあるフォーマットツールの一つになった理由の一つかもしれません。想像してみてください、tab
かspace
でインデントを制御できないフォーマットツールを使いますか?tab
とspace
の争いがほぼ五分五分の状況を考えると、このオプションがなければ、Prettier は少なくとも半分のユーザーを失うでしょう。
さらに、あまり議論のないオプションに関して、Prettier の頑固さはユーザーにいくつかの困惑をもたらすことがあります。例えば、Prettier はファイルの末尾に空行を強制的に保持しますが、これは設定できません。この動作は大多数の人に支持され、git などのツールに有利ですが、耐えられない人にとっては、彼らはハック手段を探したり、Prettier の代わりに他のツールを探さざるを得ません。
はい、私たちは dprint のような他のフォーマットツールを選ぶことができます。これはパフォーマンスが優れており、より多くの設定オプションを提供します。しかし、同様に、これは依然としてコードがいつ改行されるべきかの問題を解決していません。これはバグではなく、それらの作業モード自体によって決定されるものです。さらに、dprint の設定オプションが多くても、すべての人のニーズを満たすことは決してできません。ESLint の世界では、既存のルールのオプションを設定したり、プラグインを書くことで、自分のニーズを簡単に実現できます。
ESLint のスタイリスティックな既存のルールが jsx 内の複数の引数間のスペースを処理していないことに気づいたとき、私は現在のコードを typescript-eslint のplaygroundに置き、右側の ESTree で表示されるデータ構造に基づいてプラグインを書くことで、自分のニーズを実現できました。
拡張性#
パフォーマンスの良い言語を使用して元々js で書かれたツールを再構築することで、より良いパフォーマンスを得ることができます。しかし、これは通常代償が伴います。Rust で書かれた lint ツールは一般的にルールを簡単にカスタマイズできないため、ESLint コミュニティで非常に人気のあるルールのみが移植可能です。これは、React Compiler のリリースに伴うeslint-plugin-react-compilerのように、公式にリリースされた ESLint プラグインをすぐに利用できないことを意味します。また、ESLint コミュニティ内でニッチだが非常に有用なプラグイン、例えばESLint Plugin Commandを持つこともできません。
ルールの拡張に加えて、ESLint は lint する言語の拡張もサポートしており、現在では Vue、JSON、YAML、Toml、Markdown、Astro、Svelte などの言語で ESLint を使用してコードチェックを簡単に行うことができます。しかし、ネイティブ言語で書かれた lint ツールは、通常最も主流な言語を優先的にサポートすることしかできません。例えば、Biome を使用している場合、Vue プロジェクトを書くときには一時的に使用できず、ESLint に戻る必要があります。異なるプロジェクトで異なるツールを使用することによる不一致はあまり好きではありません。
優れたエコシステム#
このセクションでは、ESLint のプラグインエコシステムがどれほど豊富であるかを再度言及するつもりはありません。私たちはESLint VSCodeプラグインについて話しましょう。私たちが毎日使用する保存時の自動修正機能に加えて、いくつかの他の便利な機能も提供しています。
ESLint を使用する際、一部のルールは自動修正を希望しますが、保存時にすぐに修正されるわけではありません。例えば、未使用の import を削除したり、let をすぐに const に変更したり(変数に再代入する可能性があるため)します。この場合、eslint.codeActionsOnSave.rules
を設定できます。
{
"eslint.codeActionsOnSave.rules": [
"!prefer-const",
"!unused-imports/no-unused-imports",
"*"
]
}
lint-staged
とsimple-git-hooks
を組み合わせることで、エディタ内で一部のルールを無視し、コミット前に自動修正を実現できます。
もう一つ非常に便利な設定はeslint.rules.customizations
です。前述のように、一部のルールの自動修正を無効にしましたが、エディタはそれを依然としてエラーとして表示します。この設定を使用することで、これらのルールの重大度を下げたり、完全に無効にしたりできます。
{
"eslint.rules.customizations": [
{ "rule": "@stylistic/*", "severity": "off" },
{ "rule": "@stylistic/no-tabs", "severity": "default" },
{ "rule": "@stylistic/max-statements-per-line", "severity": "default" },
{ "rule": "antfu/consistent-list-newline", "severity": "off" },
{ "rule": "prefer-const", "severity": "off" },
{ "rule": "unused-imports/no-unused-imports", "severity": "off" },
{ "rule": "simple-import-sort/*", "severity": "off" }
]
}
この設定は ESLint をコードフォーマットツールとして使用する際に非常に役立ちます。エディタ内で ESLint スタイリスティックのルールのエラー表示を直接無効にし、自動修正機能を保持できます。次のバージョンでは、すべての自動修正可能なルールの重大度を調整できるようになります。
タイプ感知の lint ルール#
Rust ベースの lint ツールは非常に速いですが、タイプ情報を使用して lint する能力はありません。Josh Goldberg はRust-Based JavaScript Linters: Fast, But No Typed Linting Right Nowという記事で非常に詳細に説明しています。
oxlint は最近試みを行いましたが、これも JavaScript の速度に戻ってしまったようです。
Biome はタイプを意識した linter の実装を準備し始めました。
私があまり気にしない ESLint の「欠点」#
パフォーマンス#
oxlint や biome などのツールのパフォーマンスが ESLint をはるかに上回ることを示すベンチマークが非常に多く見られます。しかし、私の使用シーンでは、パフォーマンスの問題はそれほど重要ではないようです。
エディタ内でのリアルタイム lint や precommit 時の lint は、一般的に少数のファイルをチェックするだけで済みます。完全な lint プロセスは CI に任せることができます。CI は私たちのローカル開発プロセスをブロックすることはなく、CI でエラーが発生したときに特定のファイルをローカルで lint すれば良いのです。
私がエディタ内で依然としてパフォーマンスの問題が発生するのは、プロジェクトが徐々に大きくなり、タイプチェックに基づくルールを有効にすると、エディタの保存操作に明らかな遅延が生じる場合です。しかし、この時にタイプチェックに基づくルールを完全に妥協する必要はありません。ESLint Flat Config の柔軟性により、エディタ内で特定のルールを無効にできます。ターミナルや CI 環境では、完全な lint を行うことができます。
私自身の ESLint Config は、以下のように設定できます。
import defineConfig from "eslint-config-hyoban";
const isInEditor = !!(
(process.env.VSCODE_PID ||
process.env.VSCODE_CWD ||
process.env.JETBRAINS_IDE ||
process.env.VIM) &&
!process.env.CI
);
export default defineConfig({
typeChecked: isInEditor ? false : "essential",
});
あなたも tsslint を試してみることができます。これは TypeScript 言語サーバーとシームレスに統合された軽量チェックツールです。
非公式の推奨#
ESLint と typescript-eslint の公式は、コードフォーマットに関連するルールを廃止することを決定し、ESLint をフォーマットに使用することを推奨しないとし、Prettier などのフォーマットツールと組み合わせて使用することを推奨しています。しかし、実際にはこれは問題だとは思いません。これらのルールを廃止し、コミュニティに維持を任せることは実際には良いことです。私たちは現在ESLint Stylisticのような使いやすいツールを持っており、それは非常に良いパフォーマンスを発揮しています。
設定が複雑で、アップグレードが面倒#
最近の ESLint 9.0 は、多くの人にとって ESLint の大規模なバージョンアップが非常に複雑であると感じさせました。主な問題は、新しい設定ファイル形式が私たちに設定を再記述させることや、API のブレイキングチェンジが多くの使用しているプラグインを 9.0 で使用できなくさせることです。
しかし、私はこれは一時的な問題だと思います。新しい設定ファイルは多くの有用な新しいツールや使用法をもたらし、利点が欠点を上回ります。ESLint Config Inspectorは、私たちが設定ファイルをより良く書き、テストするのを助けてくれます。また、プロジェクトにインストールされた依存関係に基づいて動的に設定を生成することもできます(react がインストールされたプロジェクトでのみ react hooks 関連のルールを有効にするなど)。
API のブレイキングチェンジによる問題も、さまざまな方法で解決できます:
- 上流のプラグインに PR を作成して ESLint v9 に適応させる。多くの場合、数行のコードを変更するだけで済み、ESLint v9 で新しい API を使用し、古い API を互換性のために保持します。
- 一時的に ESLint v8 を使用し、プラグインの適応を待つ(私たちは依然として Flat Config を使用できます)。
- 公式が提供するESLint Compatibility Utilitiesを使用して、アップグレードを助けてもらいます。
结语#
再度強調する必要がありますが、これは私の個人的な感想と見解であり、考慮が不十分な点があるかもしれません。ぜひ私と交流し、あなたの見解を共有してください。
もし今 ESLint All In One を試したいのであれば、Anthony Fu の ESLint config から始めることをお勧めします。これは非常に多くの言語とフレームワークをサポートしており、その基盤の上で柔軟に設定を行うことができます。
もし主に TypeScript と React を書くのであれば、私の ESLint config を試してみることもお勧めします。私のルール設定の哲学は、できるだけプラグインのプリセットルールを使用し、その上で自分の習慣に合わせて調整し、strict
とtypeChecked
オプションを提供して異なるレベルの調整を行うことです。