どの開発チームにも、このような話があるはずです。プルリクエストが半日も開いたままになっている。ロジックが壊れているからでも、APIの仕様が変わったからでもなく、オブジェクトのリテラルに末尾のカンマが必要かどうかについて、2人のレビュアーの意見が食い違っているからだ。スレッドは長引く。誰かがスタイルガイドのリンクを投稿する。別の誰かが異なるガイドを提示して反論する。コードがマージされる頃には、関係者全員が、本来構築すべきだった機能の文脈(コンテキスト)を見失っている。

こうした争いはコストがかかります。シニアエンジニアの時間を何時間も浪費させ、チームメイトの間に小さな不満を生み、ジュニア開発者に「ソフトウェアエンジニアリングとは、主にセミコロンを巡る議論に勝つことだ」という誤った認識を植え付けてしまいます。最悪な点は? プロダクト側はそんなことには無関心だということです。ユーザーは、スペースかタブかの違いには決して気づきません。彼らが気づくのは、引用符の議論に夢中になっているせいで修正されなかったバグです。

一貫性は重要です。まるで一人の人間が書いたかのように見えるコードベースは、読みやすく、レビューしやすく、デバッグもしやすくなります。間違いは、その一貫性を手動で強制しようとすることです。

退屈な作業を自動化する

解決策は単純です。フォーマットから人間の判断を完全に排除することです。エゴがなく、疲れを知らないツールに任せてしまいましょう。

3つのツールを使えば、これをスマートに処理できます。

Prettier はコードを受け取り、自動的に再フォーマットします。許可を求めることはありません。行の長さや引用符のスタイル、長い関数シグネチャをどう改行するかといったことを考える必要はなくなります。ファイルを保存すれば、Prettierが一貫性を保ってくれます。

ESLint は、Prettierが触れない問題に対処します。未使用の変数、到達不能なコード、Reactフックにおける依存関係の欠落、そして歴史的にバグにつながってきたパターンを検出します。正しく設定されていれば、フォーマットには干渉せず、実際のコードの品質に集中できます。

Husky は、自動チェックをパスするまでリポジトリへのコミットをブロックする pre-commit hook をインストールします。これにより、Gitパイプラインを「提案箱」ではなく「門番(ゲートキーパー)」に変えることができます。

これらを組み合わせることで、強力なループが形成されます。ローカルでは好きなようにコードを書きます。コミットすると、ツールがコードをクリーンにし、チェックを行います。その時初めて、コードがマシンから離れます。

なぜこのスタックが機能するのか

ESLintのルールを手動で調整することに何週間も費やすこともできますが、その衝動は抑えてください。ここでの目的は、スタイルの議論を止めることであり、スタイルガイドのキュレーターという新しいフルタイムの仕事を作ることではありません。

Prettierは意図的に独自の意見を持つ(opinionated)設計になっています。設定オプションが限られているのは、すべてのオプションが将来の議論の種になるからです。デフォルト設定は合理的です。少数のオーバーライドを選び、一度書き留めたら、さっさと次に進みましょう。

ESLintをそのままにしておくと、コードの品質だけでなく、セミコロンの使用やインデントサイズといったフォーマットルールも強制しようとします。すると、両方のツールが同じ文字を編集しようとするため、Prettierとの間で摩擦が生じます。eslint-config-prettier というパッケージは、Prettierと競合するすべてのESLintルールを無効にすることで、この問題を解決します。この役割分担が極めて重要です。見た目はPrettierが、ロジックはESLintが担当します。

継続的インテグレーション(CI)でのみチェックを実行するのは、タイミングが遅すぎます。CIが失敗したときには、すでに乱雑なコードをコミットし、別のタスクにコンテキストを切り替え、さらにはプルリクエストを作成しているかもしれません。修正するには、別のコミット、別のプッシュ、そして再び待ち時間が発生します。Huskyはそのフィードバックループを数秒に短縮します。また、lint-stagedを使えば、コミットのたびにリポジトリ全体をスキャンするのではなく、実際に変更したファイルに対してのみツールを実行するため、高速に処理できます。

ステップ・バイ・ステップの設定方法

以下の設定はモダンなJavaScriptまたはReactプロジェクトを対象としていますが、微調整を加えることでTypeScript、Vue、またはNodeにも応用できます。各ステップはプロジェクトのルートディレクトリで実行してください。

まず、すべてを開発用依存関係(dev dependencies)としてインストールすることから始めます。

npm install -D prettier eslint husky lint-staged eslint-config-prettier