【テクニカル・上級編】依存関係の「幽霊」を狩る:depcheckとsyncpackでpackage.jsonをクリーンに保つ自動化パイプライン – ビルド・パッケージ管理ツール生産性向上バイブル

依存関係の「幽霊」を狩る:CI/CDを「真実のソース」へと進化させる極致

開発現場において、`node_modules`はしばしば「ブラックボックス」と化す。`package.json`には記載されていないのに、なぜか`import`できてしまう「幽霊依存(Phantom Dependencies)」。あるいは、プロジェクトの肥大化を招く「ゾンビ依存(Unused Dependencies)」。これらは単なる技術的負債ではない。ビルドの非決定性、セキュリティパッチの漏れ、そしてCIキャッシュの無駄な肥大化という、プロダクトの寿命を削る癌である。

本稿では、npm/pnpmのエコシステムにおいて、これらをCIパイプラインで完全自動的に検閲・駆逐し、リポジトリを常に「クリーンな状態」に保つための、アーキテクト級の戦略を伝授する。

—

1. 幽霊依存のメカニズム:なぜ「見えてしまう」のか

Node.jsのモジュール解決アルゴリズム(Node Resolution Algorithm)は、物理的な`node_modules`ツリーを再帰的に走査する。この際、ホイスティング(Hoisting)によって、本来依存していないはずのパッケージが上位ディレクトリに展開されると、コード上からそのパッケージをrequire/importできてしまう。これが幽霊依存の正体だ。

特にpnpmの「厳格な依存関係解決」を導入している場合、この境界線は明確だが、依然として`package.json`の記載漏れ(ビルド時のみ必要なパッケージのミス等)は発生しうる。これを静的解析で狩り取るのが、`depcheck`の責務である。

—

2. depcheckとsyncpackによる「検閲パイプライン」の構築

単に`depcheck`を走らせるだけでは不十分だ。我々が構築すべきは、「依存関係の異常を検知した瞬間にビルドを中断し、原因を特定可能な形でログを吐き出す」検閲官である。

CI工程への統合(GitHub Actions設定例)

jobs:
dependency-audit:
runs-on: ubuntu-latest
steps:

  • uses: actions/checkout@v4
  • name: Setup Node

uses: actions/setup-node@v4
with: { node-version: ’20’ }

# 1. 幽霊とゾンビを狩る

  • name: Depcheck Audit

run: |
npx depcheck –json > depcheck-report.json
# 終了コード0以外を検出してパイプラインを止める
# –ignore-bin-package等、プロジェクトごとのカスタマイズが肝
npx depcheck –ignores=”eslint-config-,@types/”

# 2. バージョンの不整合を統一する

  • name: Syncpack Audit

run: npx syncpack list-mismatches

アーキテクトの知見:depcheckのカスタマイズ

`depcheck`の標準設定では、動的インポートや特定のビルドツール(Vite/Webpack)のプラグインを検知できないケースがある。その際は、`.depcheckrc`をプロジェクトルートに配置し、解析対象外を指定するのではなく、「パーサーを拡張する」アプローチをとる。

// .depcheckrc
{
“ignores”: [“eslint-“, “prettier-“], // Lint/Format系はビルドに影響しない
“parsers”: {
“/.js”: “es6”,
“/.ts”: “typescript”
},
“detectors”: [
“requireCallExpression”,
“importDeclaration”
]
}

—

3. syncpackによるモノレポ管理の「真の自動化」

モノレポ環境では、`package.json`間でのバージョン不一致は「悪」である。`syncpack`は単なるバージョン統一ツールではない。依存関係のグラフを正規化する強力なエンジンだ。

CIで実行すべきは、単なる修正ではない。「強制的な修正」と「プルリクエストへのフィードバック」である。

現場で震えるほど役立つ、syncpackのCI実行コマンド
1. 不整合があればエラーを吐いて終了
npx syncpack list-mismatches –filter ‘!@internal/’

2. 自動修正をCI上でコミットしてプッシュするフロー(推奨)
修正が必要な場合、syncpack fix を実行し、変更をコミットしてPRに追記するオートメーションを組む
npx syncpack fix-mismatches

—

4. 低レイヤ最適化:メモリ消費とパフォーマンスのハック

数千のモジュールを持つ巨大リポジトリで、`depcheck`をCIで回すとメモリが枯渇することがある。この場合、Nodeのメモリ制限を明示的に引き上げるのが鉄則だ。

CI環境での実行コマンド最適化
NODE_OPTIONS=”–max-old-space-size=4096″ npx depcheck

また、Docker上でこれを行う際は、`node_modules`のキャッシュ戦略が重要だ。GitHub Actionsのキャッシュにおいて、`pnpm-store`と`node_modules`を分離し、`pnpm store prune`を定期実行することで、ビルド時間を数分単位で短縮できる。

—

5. 結論:依存関係を「設計」するということ

依存関係管理を「インストールする作業」から「パイプラインで自動検閲するアーキテクチャ」へ昇華させることは、エンジニアリング組織の成熟度を測るリトマス試験紙である。

1. depcheckで「不要なもの」を捨て、
2. syncpackで「不整合なもの」を正し、
3. CIパイプラインで「それらを法として強制する」。

このサイクルを確立した瞬間、あなたのチームは「なぜか動かないビルド」や「謎の幽霊パッケージ」に時間を奪われることから永久に解放される。次は、これらを`Husky`によるプリコミットフックに組み込み、開発者のローカル環境から「健全な状態」を強制するステージへ進むことを推奨する。

技術はただ使うものではない。プロジェクトの守護神として、コードベースの深淵に鎮座させるものだ。健闘を祈る。

タイトルとURLをコピーしました