Lefthookを使ってみたい!
はじめに
皆さん、どうも!
今日は私が最近知って、実際に使ってみたツール「Lefthook」についてお話しします。
Lefthookは、コードの品質管理や開発プロセスの効率化に役立つツールです。formatやlintの調整など、ローカルで確認したいCI/CDをリモートにコードをあげる前に自動で確認できるツールです。使ってみると、導入コストも高くなくてしかも並列でCI/CDできるから開発作業がスムーズになって驚きました。
今回感じたLefthookの魅力をお伝えできればと思います!!
Lefthookとは?
git hooks managerです。他の代表例で言うとHusky
になりますね。あの狼のやつ🐺
commit前やpush前にスクリプトを自動で実行することができるツールです。
代表的な使い方で言うと、lint-stagedと組み合わせてPrettierとESlintを実行させてformatやlintの調整で使われることが多いと思います。プロジェクト全体で開発していても各個人の設定が違うとみんなバラバラのフォーマットになり毎回余計な差分がPRで出てしまってレビューする側が大変ですよね😫
そんな時にLefthookを使うことで、PRを作成する前にコードのスタイルをチーム全体で一貫性を保つことができます!
git hooks
についてはこちらの方がわかりやすかったので、確認してみてください!
なぜ導入したいのか
私がLefthookを導入した理由は、主に以下の2点です:
信頼性の高い推奨
Biomeの公式ドキュメントでLefthookが紹介されているのを見て、信頼性の高いツールだと感じました。公式が書いているというのがそのツールの価値を裏付けるものでもあるのかなと思います。
新しいツールへの挑戦
Huskyは今でも問題なく使えると思います。でも自分の中で開発者として常に新しいツールに触れ、より良い選択肢を探ることは大切だと考えていていて、その中でLefthookの存在を知り触ってみたいと思いました。
(アイコンとかユニークですし🥊)
HuskyとLefthookの違いは?
HuskyとLefthookにはいくつかの違いがあります。まず、HuskyはNode.jsで作られているので、JavaScriptプロジェクトとの相性が良いと言えます。一方、LefthookはGoで作られているので、動作が速いといったのが特徴です。
設定ファイルの形式も違います。HuskyはJSONを使いますが、LefthookはYAMLを使います。
特に便利なのは、Lefthookがコマンドを並列で実行できることです。これにより、フックの実行時間を大幅に短縮できます。大きなプロジェクトでは、この並列実行がとても役立ちますね!
使い方
インストール
まずはbrewでlefthookをインストールしましょう!
brew install lefthook
そのあとプロジェクトに追加します。(bun
のところはお使いのpackage manager
に合わせてください)
bun add lefthook
追加するとrootにlefthook.yml
が生成されると思います。
中身は以下のEXAMPLEが入ってます。親切で良い!!
EXAMPLE
# EXAMPLE USAGE:
#
# Refer for explanation to following link:
# https://github.com/evilmartians/lefthook/blob/master/docs/configuration.md
#
# pre-push:
# commands:
# packages-audit:
# tags: frontend security
# run: yarn audit
# gems-audit:
# tags: backend security
# run: bundle audit
#
# pre-commit:
# parallel: true
# commands:
# eslint:
# glob: "*.{js,ts,jsx,tsx}"
# run: yarn eslint {staged_files}
# rubocop:
# tags: backend style
# glob: "*.rb"
# exclude: "application.rb|routes.rb"
# run: bundle exec rubocop --force-exclusion {all_files}
# govet:
# tags: backend style
# files: git ls-files -m
# glob: "*.go"
# run: go vet {files}
# scripts:
# "hello.js":
# runner: node
# "any.go":
# runner: go run
書き方
今回は以下に用意した例を用いて説明します。
まずは、pre-commit
pre-push
に対してコマンドを設定していきます。
pre-commit:
commands:
format:
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
run: bunx biome check --apply --no-errors-on-unmatched --files-ignore-unknown=true ./src && git update-index --again
pre-push:
commands:
format:
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
run: bunx biome check --no-errors-on-unmatched --files-ignore-unknown=true ./src
基本的にcommands以下に設定していきます。commands以下が実行されるイメージです。
formatの部分は任意で名前を変えることができます。今回はコードを整形したいのでformat
と名付けてます。
-
glob
でファイルを指定します。 -
run
で走らせたいコマンドを書きます。今回の場合はBiomeを使いたいので書いてます。
基本はこれだけです。pre-push
も基本的に同じ要領でやれば問題ありません。
並列で走らせる
ここから、Lefthookでしかできない並列にhookを走らせる方法です。
pre-commit:
parallel: true # ここに書く
commands:
format:
tags: format
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
run: bunx biome check --apply --no-errors-on-unmatched --files-ignore-unknown=true ./src && git update-index --again
tsc:
tags: tsc
glob: "*.{ts,cd.mts,tsx}"
run: bunx tsc --noEmit
parallel
をtrue
にすることでcommands以下に書かれている並列にコマンドが走ります。defaultは基本的にfalse
になっています!
biomeでフォーマットをしてその間にtscを実行することができますね!これはかなりプロジェクトによっては時間が短縮されるのではないでしょうか?
また、直列に実行させたいときやコマンドでエラーが起きた時に停止させたい場合は、parallelと同じ箇所にpiped: trueを設定することで可能です。
特定のコマンドをスキップさせたい
並列に走らせたいけど今回は特定のコマンドは必要ないなって時は以下のようにLEFTHOOK_EXCLUDE
にtags
名を指定してあげるとスキップすることができます。
LEFTHOOK_EXCLUDE=tsc git commit -m "Skip command"
関連PR
終わり
Lefthookを使ってみて、率直に言って本当に良かったです。開発プロセスが格段にスムーズになり、楽になりました。
新しいツールを試すのは少し勇気がいりますが、今回はその一歩を踏み出して良かったと感じています!
皆さんも、興味が出たらぜひLefthook使ってみてください。
Discussion