2026年09月14日 11:50 / - PV

ビルドが落ちたのをきっかけにpackage.jsonを眺めていて、見覚えのないパッケージが目に入りました。
"puppeteer": "^21.2.1",
使っている記憶がありません。
調べたら本当に使っていませんでした。それどころか、この1行のせいで毎回のビルドでChromiumがダウンロードされていました。170MB前後です。何にも使われないまま、毎回。
同じような残骸を抱えているプロジェクトは多いと思うので、洗い出し方と、消すときの確認手順を書いておきます。
使っていないだけなら、バンドルには入りません。Next.jsはimportされていないコードを出力に含めないからです。なのに害があります。
理由は主に3つです。
とくに1つ目と2つ目は、コードが1行も触れていなくても、インストールの時点で動くのがポイントです。「使っていないから無害」は成り立ちません。
うちは2つ目でビルドが落ちました。使っていないパッケージが原因で本番のデプロイが止まる、というのはなかなか間抜けな話です。
パッケージ名で全文検索すると、関係ない単語が大量に引っかかります。 importの形で探すのが確実です。
PKG=puppeteer
grep -rn "from '$PKG'\|from \"$PKG\"\|require('$PKG')\|require(\"$PKG\")\|from '$PKG/" \
--include=*.ts --include=*.tsx --include=*.js --include=*.jsx --include=*.mjs \
. | grep -v node_modules
うちのcanvasがまさにこれで、単語で検索するとBusinessModelCanvasやhtml2canvas、<canvas>要素が山ほど出て「使っている」と誤認しかけました。
コードだけでなく、設定ファイルから名前で参照されるものがあります。
package.jsonのscripts(CLIとして直接叩いているもの)grep -rn "puppeteer" package.json *.config.* .*rc* 2>/dev/null
「importされていない=使っていない」ではないのはこの層です。ここを見ずに消すと、CIだけが後から壊れます。
自分が使っていなくても、他のパッケージが依存していることがあります。yarnならこれで分かります。
yarn why puppeteer
「他のパッケージが必要としている」と出たら、package.jsonから消してもnode_modulesには残ります。それでも直接依存から外す意味はあります。 バージョンを自分で固定しなくなるので、依存元の更新に追随できるようになります。
うちのcanvasはyarn.lockを見ても依存元が存在しない残骸でした。おそらく昔なにかを試した名残です。
消して終わりにせず、ビルドを通してからコミットします。
rm -rf node_modules
yarn install
yarn build
node_modulesを消してから入れ直すのが大事です。手元に残っているだけのパッケージが動作を支えている場合、消し忘れに気づけません。
yarn.lockの差分も見ておきます。うちがpuppeteerを外したときは、
puppeteerの依存ツリー(chromium-bidi、devtools-protocol、extract-zipなど)だけが消えたという差分でした。意図しないバージョン変更が混ざっていないかは必ず確認してください。ここに気づかず一緒にコミットすると、後日「なぜか動かない」の原因が特定できなくなります。
棚卸しの最中に、package-lock.jsonとyarn.lockが両方あることに気づきました。
これは静かに効いてくる問題です。
yarn.lockを見てインストールしているpackage-lock.jsonは誰も見ていないのに存在するcanvasすら含まれていなかったつまり「lockファイルを見ても実際に何が入るのか分からない」状態でした。手元でnpmを叩いた人と、yarnを叩いた人で、別のツリーができます。
どちらか一方に決めて、もう片方は削除してください。うちはyarnに統一しました。
git rm package-lock.json
決めたあとは、依存を変えたらlockファイルを必ずコミットするのを徹底します。lockを更新しないままpushすると、本番だけ別のバージョンが入る余地が残ります。
参考までに、うちの規模(ページ50本以上、ビルドマシンは2コア)での実測値です。
| 状況 | 所要時間 |
|---|---|
| キャッシュ無し(初回・依存変更後) | 約12分 |
| キャッシュ有り+依存変更あり | 約1分40秒 |
| キャッシュ有り+コード変更なし | 約42秒 |
念のため書いておくと、これは依存を消したことによる短縮の数字ではありません。 キャッシュが効くかどうかの差です。
ここで言いたいのは、依存を変えるとキャッシュが無効になるということのほうです。つまり不要な依存が残っていると、それが更新されるたびに12分側を引きます。効いてくるのは「毎回のビルドが数秒速くなる」ではなく、遅いビルドを踏む頻度のほうです。
depcheckのようなツールで自動化できませんか?洗い出しの取っかかりには便利です。ただ設定ファイル経由の参照や、CLIとして使っているものを誤検出しがちなので、出力をそのまま信じて消すのは危険です。
「候補を出させて、1つずつ手で確認する」という使い方が現実的だと思います。今回のように十数個ならgrepで十分でした。
devDependenciesとdependenciesの区別は直すべきですか?気づいたなら直しておくといいです。本番ビルドでdevDependenciesを入れない構成にしたとき、初めて痛い目を見ます。
ただしNext.jsのビルドはdevDependenciesを必要とするので、Vercelでは両方インストールされます。「直さないと壊れる」類の話ではありません。優先度は低めです。
戻せばいいだけです。gitに履歴が残っているので、バージョンごと復元できます。
消すのを怖がって残し続けるほうがコストが高いというのが今回の結論でした。使っていないものが原因で本番が止まった実績があるので、なおさらです。
依存を変えたあとの検証では、「Use existing Build Cache」を外してビルドしてください。旧環境の成果物が残っていると、検証になりません。
普段のデプロイでは、もちろん有効のままで構いません。
node_modulesごと入れ直してビルドを通してからコミットyarn.lockの差分に意図しないバージョン変更が混ざっていないか確認するpackage-lock.jsonとyarn.lockの併存は解消するpackage.jsonは、放っておくと過去に試したことの墓場になります。年に一度でも棚卸しすると、こういう地雷が減ります。
この記事が何かのお役に立てれば幸いです。
最後までお読みいただきありがとうございました!
Share Me!