Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

git でブランチを切り替えたとき、node_modules を更新する (キャッシュ機構付き)

結論: 以下を .git/hooks/post-checkout に追加

#!/bin/sh
PREV_BRANCH=`git reflog show -q | head -n1 | awk '{print $6}'`
CACHE_DIR=~/.cache/my_project_node_modules
mkdir -p $CACHE_DIR
prev_node_modules_cache="$CACHE_DIR/$(git show $PREV_BRANCH:package.json | shasum | awk '{print $1}')-$(git show $PREV_BRANCH:package-lock.json | shasum | awk '{print $1}')"
cur_node_modules="$CACHE_DIR/$(shasum package.json | awk '{print $1}')-$(shasum package-lock.json |awk '{print $1}')"

if [ "$prev_node_modules_cache" = "$cur_node_modules" ]; then
  exit
fi

mv node_modules $prev_node_modules_cache
if [ -d "$cur_node_modules" ]; then
  mv $cur_node_modules node_modules
else
  npm ci
fi

解説

package.json と package-lock.json をキーに、node_modules を ~/.cache/my_project_node_modules へ保存している。

  • 切り替え前のブランチと package.json も package-lock.json も同一の場合: 特に何もしない (同じ node_modules を使う)
  • 切り替え前のブランチと package.json か package-lock.json が異なる場合:
    • まず、今の node_modules をキャッシュディレクトリに移動する
    • 既にキャッシュが存在する場合: キャッシュディレクトリから適切な node_modules を持ってくる
    • キャッシュが存在しない場合: npm ci を行う

node_modules をコピーではなく移動させているだけなので、かなり軽快に動作する。

(ざっとしか検証してないので、動かなかったらコメントお願いします)