pre-commitのLintチェック、チームで入れる前に決めておきたいこと!HuskyとLefthookの比較も
🙌 結論から
コミット後にCIで lint エラーやフォーマット崩れが見つかって、「またやり直しか…」となる回数が、Husky と lint-staged の導入でほぼゼロになりました!
pre-commit のタイミングでステージしたファイルだけを自動でチェック・整形してくれるので、コミットした時点で品質がある程度保証されます。
チーム開発でレビュアーが「インデントが揃ってない」と指摘する手間も減って、さりげなく効果が大きい仕組みでした(^^)
💡 以前の問題
以前のプロジェクトでは、ESLint や Prettier の実行をCIに任せきりにしていました。
その結果、ローカルではエラーに気づかずコミット・プッシュしてしまい、CIが落ちてから慌てて修正することがよくありました。
# CI でようやく気づくパターン
git push origin feature/xxx
# → CI落ちる → 手元で lint 実行 → 修正 → 再プッシュ
この「CIで落ちてから気づく」というサイクルは、レビュー待ちの時間も無駄に伸ばしてしまいます。
レビュアー側も、本質的でないフォーマットの指摘にコメントを使うのは正直あまり気持ちのいいものではなく…
👀 Husky + lint-staged を導入する
まずは Husky と lint-staged をインストールします。
npm install -D husky lint-staged
npx husky init
package.json に lint-staged の設定を追加します。
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
]
}
}
.husky/pre-commit に lint-staged を実行する1行を書くだけで設定は完了です。
npx lint-staged
これで git commit を実行するたびに、ステージされたファイルだけを対象に lint と整形が自動で走るようになります。
全ファイルではなくステージ済みファイルだけが対象なので、大きなリポジトリでも実行時間が気にならないのがうれしいポイントです🙌
✨ 導入してみた感想
導入してすぐに感じたのは、レビューのコメント数が減ったことです。
フォーマットやちょっとした lint 違反はコミット時点で自動修正されるので、レビュアーはロジックの妥当性に集中できるようになりました!
もちろん pre-commit のチェックに時間がかかりすぎると、コミットのたびにストレスを感じてしまうので、対象を --staged のファイルに絞っておくのは重要だと感じます。
たまに「--no-verify でチェックをスキップしたい」場面もありますが、これは緊急時以外は使わないルールをチームで決めておくと安心かも?
CIでのチェックも残しておけば、pre-commit をすり抜けたケースの最後の砦になってくれます。
⚡ Lefthookという速い選択肢も検討した
Husky + lint-staged の構成に満足していたんですが、チームメンバーから「大きいリポジトリだとコミットのたびに待たされる」という声が出て、代替の Lefthook も試してみました。
Lefthook は Go 製のGitフック管理ツールで、フックを並列実行できるのが最大の特徴です。
# lefthook.yml
pre-commit:
parallel: true
commands:
lint:
glob: "*.{ts,tsx}"
run: eslint --fix {staged_files}
format:
glob: "*.{ts,tsx,json,md}"
run: prettier --write {staged_files}
Husky + lint-staged は各チェックを順番に実行するのに対して、Lefthook は lint と format を同時に走らせられます。
大きめのリポジトリで比較したところ、体感でコミットにかかる時間がかなり短くなった印象でした(・∀・)
設定ファイルも lefthook.yml の1つにまとまるので、.husky/pre-commit と package.json の lint-staged フィールドに分かれていた設定が1箇所にまとまるのも意外と嬉しいポイントです。
ただ、Husky のほうがエコシステムとしての情報量が圧倒的に多く、チームに新しく入るメンバーへの説明のしやすさも含めると、まだ移行に踏み切れていません。
「速さを取るならLefthook、実績と情報量の安心感を取るならHusky」というのが、今のところの私の結論です。新規プロジェクトなら一度Lefthookも比較検討する価値があると思います。
🤔 チームで入れるときに決めておきたいこと
Husky と lint-staged は、入れる前にチームで少しだけ決めておくと揉めずに済みます(^^)
--no-verifyで飛ばしていいか: 急ぎのときに pre-commit を飛ばす抜け道。使っていいケースを決めておく- 重いチェックはどこでやるか: 型チェックやテストは pre-commit だと遅いので、CI に任せる
- 自動整形の範囲: Prettier で全部整形すると、関係ない差分がレビューに混ざる。最初に一度だけ全体を整形するコミットを作っておく
特に2つ目が大事で、pre-commit は「数秒で終わるチェックだけ」に絞るのがコツです👀
コミットのたびに30秒待たされると、みんな --no-verify を使い始めて、結局意味がなくなります(・_・;)
私のおすすめの分け方はこんな感じです。
| タイミング | やること |
|---|---|
| pre-commit | ステージしたファイルの lint・整形だけ |
| CI | 型チェック・テスト・全ファイルの lint |
速いチェックは手元で、重いチェックは CI でと分けると、続けやすい仕組みになります✨
パパ系Webエンジニア〜愛用ガジェット一覧 🛍️
この記事を書いている作業環境のガジェットを楽天ROOMにまとめています ✨ 在宅エンジニアのデスク作りの参考にどうぞ 🙌
👍 まとめ
Husky と lint-staged の組み合わせは、**「コミット前にステージ済みファイルだけを自動チェックする」**というシンプルな仕組みながら、効果はかなり大きいです!
CIで落ちてから気づく手戻りが減るだけでなく、レビューでの本質的でない指摘も減らせます。
まだCIだけに lint を任せているプロジェクトがあれば、pre-commit フックを仕込んでみる価値は十分にあると思います(^o^)/
※ 各ツールのバージョンや機能は今後も更新されます。最新情報は Husky公式ドキュメント をご確認ください👀