前言#
これは 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
オプションを提供して異なるレベルの調整を行うことです。