【React】huskyでコードフォーマットとコミットメッセージ生成を自動化する
tl;dr
pnpm add -D husky lint-staged eslint prettier eslint-config-prettier prettier-plugin-tailwindcss commitlint commitlint-config-gitmoji commitizen cz-customizable
pnpm exec husky install
pnpm exec husky add .husky/pre-commit 'pnpm exec lint-staged'
pnpm exec husky add .husky/commit-msg 'pnpm exec -- commitlint --edit $1'
pnpm exec husky add .husky/prepare-commit-msg "exec < /dev/tty && node_modules/.bin/cz --hook || true"
{
"scripts": {
+ "prepare": "husky install"
},
+ "lint-staged": {
+ "*.{js,jsx,ts,tsx,json,md}": [
+ "prettier --write"
+ ]
+ },
+ "config": {
+ "commitizen": {
+ "path": "cz-customizable"
+ }
+ }
}
module.exports = {
plugins: [require("prettier-plugin-tailwindcss")],
};
module.exports = {
extends: ["gitmoji"]
};
module.exports = {
types: [
{ name: "feat \t\t✨ 新機能追加", value: "✨ feat" },
{ name: "fix \t\t🐛 バグ修正", value: "🐛 fix" },
{
name: "test \t\t✅ テストの追加や既存テストの修正",
value: "✅ test",
},
{
name: "refactor \t🔨 バグ修正や新機能追加以外のコード修正",
value: "🔨 refactor",
},
{
name: "style \t💄 プログラムの動きに影響を与えない変更",
value: "💄 style",
},
{ name: "docs \t\t📝 ドキュメントのみの変更", value: "📝 docs" },
{
name: "perf \t\t⚡ パフォーマンス改善のためのコード修正",
value: "⚡ perf",
},
{
name: "chore \t🔧 ビルドプロセスやドキュメント生成のような補助ツールやライブラリの変更",
value: "🔧 chore",
},
],
skipQuestions: ["body", "footer"],
scopes: ["api", "ui"],
allowCustomScopes: true,
subjectLimit: 100,
};
はじめに
開発体験を向上させるために、Prettierなどのフォーマッタを導入したり、コミットメッセージのルールを設けたりすることがあると思います。
特にチームで開発している場合、統一したルールを設定したり、そのためのツールを導入することは必須と言えます。
しかし、せっかく設定したルールをついつい忘れてしまうことがあります。
その結果、フォーマット忘れによってコードに余計な差分が発生してしまったり、コミットメッセージの書き方がバラバラになったりします。
そこで、huskyを導入して統一的なGit hooksの環境を構築します。
前提
以下の開発環境に導入することを想定しています。
- React
- TypeScript
- tailwindcss
- pnpm
プロジェクトにGit hooksを導入する
Git hooksを設定すると、コミット時にフォーマッタをかけるといったことを自動的に行うことができます。
しかし、Git hooksの設定は.git/hooks/
にインストールされるため、Gitで管理することができません。
このままではローカルにレポジトリをクローンするたびに手動でGit hooksの設定をする必要があります。
そこで、Git hooksを管理するためのライブラリhuskyをインストールします。
pnpm add -D husky
# npmの場合
npm install -D husky
# yarnの場合
yarn add --dev husky
インストールしたら、以下のコマンドでGit hooksを有効にします。
pnpm exec husky install
# npmの場合
npx husky inistall
# yarnの場合
yarn run husky install
レポジトリをローカルにクローンした際に自動でhuskyをインストールするように、package.json
に設定を追加します。
{
"scripts": {
+ "prepare": "husky install"
}
}
// npmも同様
{
"scripts": {
+ "prepare": "husky install"
}
}
// yarnの場合
{
"scripts": {
+ "postinstall": "husky install",
+ "prepack": "pinst --disable",
+ "postpack": "pinst --enable"
}
}
これでチーム内でGit hooksの設定を共有することができるようになりました👏
コミット時に自動でコードをフォーマットするようにする
ステージされているファイルにフォーマッタをかけるために、lint-stagedをインストールします。
pnpm add -D lint-staged
次に、実際にlint-stagedで実行するリンタ(ESLint)やフォーマッタ(Prettier)をインストールします。
pnpm add -D eslint prettier eslint-config-prettier prettier-plugin-tailwindcss
その後、以下のコマンドで対話的にESLintの設定ファイル.eslintrc.*
を作成します。
pnpm exec eslint --init
加えて、Prettierの設定ファイルを作成します。
とりあえずtailwindcssのためのプラグインを実行するための記述のみを書きます。
module.exports = {
plugins: [require("prettier-plugin-tailwindcss")],
};
そして、lint-stagedで使用するフォーマッタと対象ファイルをpackage.json
で指定します。
+ "lint-staged": {
+ "*.{js,jsx,ts,tsx,json,md}": [
+ "prettier --write"
+ ]
+ }
最後に、コミットの直前にlint-stagedを実行するように、huskyに設定を追加します。
pnpm exec husky add .husky/pre-commit 'pnpm exec lint-staged'
これで必ずフォーマット済みのコードをコミットできるようになりました👏
コミット時に自動でコミットメッセージの形式を検査する
コミットする直前にコミットメッセージが特定の形式になっているかどうかをチェックします。
今回は、コミットメッセージの接頭辞を絵文字にするgitmojiの設定をします。
まずは、commitlint本体とgitmojiの設定をインストールします。
pnpm add -D commitlint commitlint-config-gitmoji
次に、commitlintでgitmojiの設定を使うための設定ファイルを記述します。
module.exports = {
extends: ["gitmoji"]
};
最後に、コミット時にcommitlintを実行するように、huskyに設定を追加します。
pnpm exec husky add .husky/commit-msg 'pnpm exec -- commitlint --edit $1'
これでコミットメッセージのルールを遵守できるようになりました👏
対話的にコミットメッセージを書くようにする
commitlintを導入することでgitmojiの形式になっていることは保証できますが、コミットメッセージを書くたびにいちいちルールを思い出すのは骨が折れます。
そこで、対話的にコミットメッセージ書くようにし、確実にルールに沿ったコミットメッセージになるようにします。
まず、commitizenをインストールします。
設定をカスタマイズするために、cz-customizableも同時にインストールします。
pnpm add -D commitizen cz-customizable
package.json
に記述を追加します。
+ "config": {
+ "commitizen": {
+ "path": "cz-customizable"
+ }
+ }
そして、commitizenにルールを追加します。
今回はgitmojiのためのルールになります。
module.exports = {
types: [
{ name: "feat \t\t✨ 新機能追加", value: "✨ feat" },
{ name: "fix \t\t🐛 バグ修正", value: "🐛 fix" },
{
name: "test \t\t✅ テストの追加や既存テストの修正",
value: "✅ test",
},
{
name: "refactor \t🔨 バグ修正や新機能追加以外のコード修正",
value: "🔨 refactor",
},
{
name: "style \t💄 プログラムの動きに影響を与えない変更",
value: "💄 style",
},
{ name: "docs \t\t📝 ドキュメントのみの変更", value: "📝 docs" },
{
name: "perf \t\t⚡ パフォーマンス改善のためのコード修正",
value: "⚡ perf",
},
{
name: "chore \t🔧 ビルドプロセスやドキュメント生成のような補助ツールやライブラリの変更",
value: "🔧 chore",
},
],
skipQuestions: ["body", "footer"],
scopes: ["api", "ui"],
allowCustomScopes: true,
subjectLimit: 100,
};
最後に、コミット時にcommitizenを実行するように、huskyに設定を追加します。
pnpm exec husky add .husky/prepare-commit-msg "exec < /dev/tty && node_modules/.bin/cz --hook || true"
これでコミットメッセージのルールを覚えずに済むようになりました👏
最後に
開発体験を向上させるために、こうした環境構築はどんどんしていきたいです。
参考
Discussion