Vinyl

Husky, lint-staged から lefthook に乗り換える

はじめに

huskylint-staged は、Git フックを利用してコミットやプッシュのタイミングでコードのフォーマットや静的解析を行うためのツールとして広く使用されています。更に、lint-staged を使えば、ステージングされたファイルのみに対して処理を適用できるため、セットでよく使われいると認識しています。

しかし、プロジェクトが大きくなるにつれて、husky の設定や動作が複雑になり、パフォーマンス面での課題も出てくるようで、更に実際にかなり実行速度の違いがあるようです。

この記事では、huskylint-staged から lefthook に移行する方法を解説します。

Husky, lint-staged と lefthook の違い

項目Husky + lint-stagedlefthook
言語・依存性JavaScript (Node.js 必須)Go (シングルバイナリ、Node.js 不要)
設定の柔軟性比較的柔軟だが、設定ファイルが分散しやすいYAML で一元管理、個人設定も可能 (lefthook-local.yml)
パフォーマンスNode.js 上で動作するためやや遅いGo で実装されているため高速
エコシステムの汎用性主に Node.js 向け多言語対応、Node.js 以外でも利用可能

なぜ lefthook の方が良さそうなのか?

  • チームと共通設定を共有しつつ、個人用のカスタマイズが可能
    • lefthook はプロジェクト全体で共通のフック設定(lefthook.yml)を利用できますが、同時に個人用の設定(lefthook-local.yml)も可能です。たとえば、特定のメンバーが独自のフックを使いたい場合や、特定のフックを無効化したい場合に柔軟に対応できます。
  • 高速で軽量
    • Go 言語で書かれているため、husky よりも高速に動作します。また、シングルバイナリで動作するため、インストールやセットアップが簡単です。
  • 多言語対応
    • Node.js 以外のエコシステムでも簡単に導入でき、特に多言語混在のプロジェクトや CI/CD 環境で強みを発揮します。
  • シンプルな設定
    • YAML 形式で設定を一元管理できるため、husky + lint-staged のような複雑な設定ファイルを必要としません。

実際に移行する

husky lint-staged のアンインストール

まず、既存の huskylint-staged をアンインストールします。

npm uninstall husky lint-staged

また、.husky ディレクトリが残っている場合は削除します。

rm -rf .husky

lefthook のインストール

次に、lefthook をインストールします。

npm install lefthook --save-dev

lefthook.yml の作成

lefthook の設定ファイル lefthook.yml をプロジェクトルートに作成します。以下は、tsc, eslint, prettierを走らせている例です。pre-commitなので{staged_files}にてステージングされたファイルにだけ実行されるようにしています。

lefthook.yml

pre-commit:
  commands:
    type-check:
      run: npx tsc --noEmit
    eslint:
      glob: '*.{js,jsx,ts,tsx}'
      run: npx npm run lint --fix --file {staged_files}
    prettier:
      glob: '*.{js,jsx,ts,tsx}'
      run: npx prettier --write {staged_files}

Git フックのセットアップ

以下のコマンドを実行して、lefthook を Git フックとして登録します。

npx lefthook install

これにより、.git/hooks ディレクトリに必要なフックが配置され、設定は完了です。

npx lefthook install実行時に.husky が自動生成される件

問題の原因

lefthook をインストールした際に、.husky ディレクトリが自動生成される場合があります。これは、以前 husky を使用していたプロジェクトで、Git の設定が変更されていることが原因です。

具体的には、husky が Git の core.hooksPath.husky に設定している可能性があります。この設定が残っていると、lefthook.husky を使用しようとします。

解決策

以下の手順で問題を解決します。

  • core.hooksPath設定を確認・削除

    git config core.hooksPath

    結果が .husky の場合、以下のコマンドで設定を削除します。

    git config --unset core.hooksPath
  • .husky ディレクトリの削除

    rm -rf .husky
  • lefthook の再インストール :

    npx lefthook install

まとめ

huskylint-staged の組み合わせはまだまだ多そうですが、大規模ブロジェクトではかなり大きく実行速度に差がでるようなので積極的に提案していきたいと思います。

参考

Introduction - Lefthook Documentationfavicon iconlefthook.dev

GitHub - evilmartians/lefthook: Fast and powerful Git hooks manager for any type of projects.Fast and powerful Git hooks manager for any type of projects. - evilmartians/lefthookfavicon icongithub.com