ESLint & Prettierの深淵:CI/CDを極める「ゼロ・コンフリクト」アーキテクチャ
開発現場でよく目にする「ESLintとPrettierの競合」という泥沼。これを単なる設定ファイルのコピペで解決しようとするのは、素人のやり方だ。真のアーキテクトは、ツールが内部でどのようにAST(抽象構文木)を解釈し、プロセスのライフサイクルをどう管理しているかを掌握し、パイプラインの計算資源を1ミリ秒たりとも無駄にしない構成を構築する。
本稿では、2024年以降の標準となりつつある「Flat Config」時代の最適解と、CI/CDで死なないための極限チューニングを伝授する。
—
1. 誤解の解消:なぜ `eslint-plugin-prettier` は捨てられるべきか
かつては `eslint-plugin-prettier` を使って、ESLintのプロセス内でPrettierを実行させるのが定石とされていた。しかし、これは現代のアーキテクチャでは「悪手」だ。
- 理由: ESLintのプラグインとしてPrettierを動かすと、ESLintのルールとしてコードを整形するため、本来のPrettierの高速なファイルシステム・アクセスの恩恵を受けられず、ESLintのメモリ消費が跳ね上がる。
- 真実: ESLintは「コードの品質(論理的整合性)」に専念させ、Prettierは「コードの見た目(フォーマット)」に専念させる。これらを完全に分離し、`eslint-config-prettier` で「Prettierと衝突するESLintルールを無効化する」ことだけを目的とすべきだ。
2. Flat Config (ESLint v9+) の設計思想と実装
ESLint v9のFlat Configは、オブジェクトの配列でルールを管理する。これにより、複数の設定ファイルが複雑にマージされる従来の問題が解消された。
// eslint.config.mjs
import js from “@eslint/js”;
import prettierConfig from “eslint-config-prettier”; // 競合ルールを無効化するだけの薄い設定
export default [
js.configs.recommended,
prettierConfig, // 最後に読み込むことで、Prettierと重複するESLintルールを完全に上書き殺害する
{
rules: {
“no-console”: “warn”, // ビジネスロジックに影響する品質ルールのみを記述
“prefer-const”: “error”
}
}
];
この設計により、メモリ上でのAST走査が最適化され、TypeScriptの型情報を必要とするルール(`@typescript-eslint`等)を動かす際も、パス解決のオーバーヘッドが劇的に減る。
—
3. CI/CDパイプラインでの最適化:なぜ「並列」と「キャッシュ」か
CI/CDにおいてESLintを実行する際、単に `eslint .` を実行するのは愚策だ。大規模リポジトリでは、変更されたファイルだけを走査する「差分解析」が必須となる。
独自自動化スクリプトによる最適化 (CI環境用)
GitHub Actions等の環境で、`lint-staged` を活用しつつ、CI実行時には以下のようなシェルで並列実行を制御する。
–cache フラグは必須。CIではキャッシュディレクトリをGHAのキャッシュアクションに紐付ける
–parallel は、大規模環境でCPUコアを使い切るための魔法の鍵
npx eslint . –cache –cache-location .eslintcache –parallel
パイプライン設計の極意:
Docker環境でのCIでは、ESLintの実行プロセスが大量のファイルを開くため、`fs.inotify.max_user_watches` の制限に引っかからないよう、Dockerfile内で適切にチューニングしておく必要がある。
Dockerfileの最適化
ホストのファイルシステムを監視する場合、inotifyの監視上限を上げる
RUN echo “fs.inotify.max_user_watches=524288” >> /etc/sysctl.conf
—
4. 現場で震えるほど役立つ「lint-staged」の深掘り
PrettierをCIで実行する際、多くのエンジニアは「フォーマット違反があったらエラーを吐いて落とす」という設定にしがちだ。これは生産性を下げる。
アーキテクトの推奨設定:
`lint-staged` を使い、コミット前にローカルで整形を強制する。CIでは「チェック」のみを行い、エラーがあれば「修正済みの差分」を自動でPRに反映させるCIボットを導入する方が、エンジニアの心理的負荷は圧倒的に低い。
// .lintstagedrc.json
{
“.{js,ts,tsx}”: [
“prettier –write”, // 整形
“eslint –fix” // 修正可能なものは修正
]
}
—
5. パフォーマンス・チューニングの真髄
ESLintのパフォーマンスを極限まで引き上げるには、「不要なファイルの除外(Ignore)」を極めろ。
`node_modules` の除外は当然だが、大規模な自動生成コード(`generated/` 等)や、テスト用のダミーデータが含まれるディレクトリは、`eslint.config.mjs` の `ignores` 配列で厳格に指定せよ。これを怠ると、ESLintは不要なASTを生成し続け、CIのメモリ消費量を300%〜500%増大させる。
// eslint.config.mjs
export default [
{
ignores: [“/dist/“, “/generated/“, “/.next/“], // 不必要なパスを走査対象から物理的に切断
},
// …設定
];
まとめ
ESLintとPrettierの連携は、もはや「設定ファイルを合わせる」次元ではない。「いかにしてASTの走査を最小化し、CIパイプラインの実行時間を短縮し、開発者の脳内リソースを奪わないか」というアーキテクチャの問題だ。
これらを掌握したエンジニアだけが、技術的負債を最小限に抑え、コードの品質を担保し続ける「最強の環境」を手に入れることができる。君が今触っているそのコードベースは、単なるテキストの集まりではない。システムという生命体の設計図であることを忘れるな。