【Node.js】フォーマッター・リンターをコミット時に実行する(パッケージ非依存)


はじめに

Node.jsプロジェクトの品質を保つためコミット時にフォーマッターやリンターをかけるのを強制したい時、huskylint-stagedを使用する例が散見されます。ですが、この目的のためだけに依存関係を増やしたくない場合もあるでしょう。
この記事では、これらのパッケージに依存することなくpre-commitフックを共有し、Prettierとリンターをコミット時に必ず実行させる方法を紹介します。

やり方

  1. .githooks/pre-commitファイルをつくり以下のように記載します。
.githooks/pre-commit
#!/bin/sh
FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g')
[ -z "$FILES" ] && exit 0

npm run lint \
&& echo "$FILES" | xargs ./node_modules/.bin/prettier --ignore-unknown --write \
&& echo "$FILES" | xargs git add
  1. package.jsonに以下の行を追記します。
package.json
{
  "scripts": {
+   "postinstall": "git config --local core.hooksPath .githooks && chmod -R +x .githooks/"
  }
}
  1. installを行います。
$ npm install

説明

.git配下のファイルなどはgit管理されません。そのため、Gitのバージョン2.9より追加されたhooksの置き場を任意に指定できる機能を使い、.githooksディレクトリを使用するようにします。
このディレクトリは任意の名前にして問題ありません。ただし、ファイル名は一致させる必要があります。

.githooks/pre-commit
#!/bin/sh
FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g')
[ -z "$FILES" ] && exit 0

npm run lint \
&& echo "$FILES" | xargs ./node_modules/.bin/prettier --ignore-unknown --write \
&& echo "$FILES" | xargs git add

Prettierのドキュメントを参考にしています。

https://prettier.io/docs/en/precommit.html#option-6-shell-script
FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g')

ステージ上にあるファイルの一覧を取得し、変数に入れています。


npm run lint

package.jsonlintスクリプトが記載されている前提のコードとなっています。
eslintを使用している場合は以下のようにするとよいでしょう。

./node_modules/.bin/eslint --cache .
echo "$FILES" | xargs ./node_modules/.bin/prettier --ignore-unknown --write

前述した一覧を渡すことで、ステージ上にあるファイルのみフォーマットされるようにしています。

echo "$FILES" | xargs git add

ここまでの処理による変更をステージ上に反映させます。

これらを&&で繋ぐことで、lintエラーが出たりフォーマットが失敗したりした段階でコミットが中止されるようにしています。


package.json
"postinstall": "git config --local core.hooksPath .githooks && chmod -R +x .githooks/"

postinstallスクリプトはインストールが終わった後に実行されます。
このときに、gitのフックのパスを先ほど作成したフォルダにしその配下のスクリプトが使われるように変更しています。