🛠️

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

2022/04/03に公開

はじめに

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
    

  2. [Linux/macOS].githooks/ディレクトリ内のファイルに実行権限を付与する

    chmod +x .githooks/*
    
  3. package.jsonに次の行を追記する

    package.json
    {
       "scripts": {
    +   "postinstall": "git config --local core.hooksPath .githooks"
      }
    }
    

  4. installを行う

    npm install
    
  5. ステージしてコミット

    git add --chmod=+x -- .githooks/
    
    git add -- package.json
    
    git commit
    

説明

.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"

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

GitHubで編集を提案

Discussion