package.json が膨らんだ僕が使わないライブラリを見極めた話
大掃除の判断基準 3 つ
package.json を開いて、こんな経験はありませんか?
「このライブラリ、いつ入れたんだろう」
「これ、今のコードで使っているのかな…」
「消したら壊れそうで、怖くて触れない」
フリーランスになって個人開発(tsurilog・flowtask)と並行してクライアント案件を複数こなすようになってから、この感覚が何度も来るようになりました。
プロジェクトを立ち上げるたびに増えていく依存関係。
削る判断基準がないまま、「動いているし、今はいいか」と先送りにし続けた結果——気づいたときには、見覚えのないライブラリが package.json にズラリと並んでいたのです。
これは、3 つの判断基準と depcheck を使って package.json を整理した、僕の記録です。
「動いているものに触るな」 という呪い
「動いているものに触るな」
——現場でよく聞く言葉です。
納期の直前、本番の真横。
その言葉は確かに効く。
かつての僕は、それを正義だと思っていました。
緑の CI が出ているなら追加の冒険はしない。
npm audit が赤くても build が通るなら、今はやめておく。
この「今はいいか」が積み重なると、怖いことが起きます。
package.json の行数が増え続ける。
何のために入れたか分からないライブラリが並ぶ。
「削れるはずなのに、削る根拠が言語化できないから触れない」
という状態になる。
これは怠慢ではありません。
削る判断基準がないまま時間が経つほど、削ることへの心理的コストが上がっていくのです。
コード哲学として書いた「バージョンを上げる勇気」でも触れましたが、止まったままの依存関係には静かな利息がつきます。
セキュリティの穴は、僕の都合を待ってくれない。
「いつか整理しよう」は、「ずっと整理しない」に変わりやすい。
package.json が膨らんでいった経緯
僕の場合、ライブラリが増えていったパターンは主に 3 つでした。
【パターン ①】 チュートリアル通りに npm install
新しいフレームワークやライブラリを学ぶとき、公式ドキュメントの npm install をそのまま実行する。
学習目的で入れたものが、そのままプロジェクトに残り続ける。
GW に Bun・Hono・Astro を並べた素振り記録を書いたとき、本番に繋げない約束で触ることにしました。
その試行用のプロジェクトに入れたライブラリが、本番のリポジトリとごっちゃになって残ることが何度かありました。
【パターン ②】 「いつか使うかも」で試したまま放置
気になったツールを npm install して試したものの、結局使わなかった。
削除するタイミングを逃したまま package.json に残っている。
特に状態管理ライブラリがこのパターンに多かった印象です。
Zustand を入れて使い始めたのに、別の部分では古い Context のままで、二重管理になっていたことがあります。
【パターン ③】 過去プロジェクトの package.json を丸ごとコピー
新しいプロジェクトを始めるとき、前のプロジェクトの設定をベースにする。
前のプロジェクトで使っていたライブラリが、新しいプロジェクトでは不要なまま入ってくる。
特に 3 つ目は個人開発あるあるで、tsurilog(釣果記録アプリ)と flowtask(GTD × PDCA の Todo アプリ)では用途が全然違うのに、同じ package.json をコピーして始めたことがありました。
tsurilog には地図関連のライブラリが必要で、flowtask には不要——なのに両方に入ったままになっていた。
ESLint から Biome に移行したときも、「なぜこのプラグインが入っているのか」を説明できないものが複数あった。
依存が積み重なると、削る前に「これは本当に使っていないのか」を確認すること自体がコストになるのです。
これらのパターンに共通しているのは、入れる判断は一瞬だが、削る判断は後回しにしやすいということです。
インストールはコマンド 1 行で終わる。
削除するときは「壊れないか?」という確認コストが乗ってくる。
この非対称性が、package.json を膨らませていく本質的な原因だと思っています。
depcheck を初めて実行した日
転機になったのは、depcheck を初めて実行したときでした。
npx depcheck出力を見て、少し驚きました。
Unused dependencies
* moment
* @types/lodash
* eslint-plugin-import
* react-icons
...
Unused devDependencies
* @testing-library/user-event
* jest-environment-jsdom
...実際には import すら存在しないライブラリが複数あった(汗)
「これ、いつ入れたんだろう」と首をかしげるものがいくつかある。
depcheck は、プロジェクト内のソースコードを解析して「実際には使われていない依存関係」を洗い出してくれるツールです。
インストールは不要で、npx でそのまま実行できます。
この出力を見て、「削ってもいいものがこんなにある」と初めて可視化された気がしました。
ただ、depcheck の出力をそのまま全部削除するのは危険です。
間接依存として他のパッケージが使っているものや、設定ファイルの中だけで参照されているものも未使用として出てくることがあるからです。
だから次に必要なのは、削るかどうかを判断する基準です。
判断基準 3 つ
実際に使っている判断フローを整理すると、3 つのステップになります。
【基準 ①】 直接 import しているかを確認する
depcheck の出力を見た後、実際にプロジェクト内を検索します。
# パッケージ名で grep して import の有無を確認
grep -r "from 'moment'" src/
grep -r "require('moment')" src/import が 0 件なら、削除候補の筆頭です。
ただし例外があります。
設定ファイル(next.config.js、vite.config.ts など)の中でのみ参照されているパッケージは、src/ 以外の場所にあることがあります。
depcheck はデフォルトで設定ファイルも解析しますが、確信が持てない場合はプロジェクト全体を検索します。
【基準 ②】 間接依存か直接依存かを npm ls で確認する
npm ls moment出力例:
myproject@1.0.0
└── some-other-package@2.0.0
└── moment@2.29.4このように、自分は直接使っていないが、他のパッケージが依存している場合は、削除しても node_modules には残ります(他が依存しているので)。
逆に言えば、package.json から削除しても問題ない—— npm install 後は引き続き node_modules に存在するからです。
直接依存として package.json に書いておく意味がないなら、削除してすっきりさせましょう。
【基準 ③】 セキュリティ警告があるかを確認する
npm auditdepcheck で使っていないと分かったライブラリに npm audit の警告も出ている場合、優先的に削除します。
使っていないのにセキュリティリスクを抱えているのは、メリットがゼロでリスクだけある状態です。
この 3 つを順番に確認することで、
「削っていいもの」
「削ると壊れるかもしれないもの」
「削っても node_modules には残るもの」
を整理できます。
【補足】 bundle analyzer でサイズへの影響を可視化する
depcheck で使っていないことは分かっても、削ったときどのくらい軽くなるか知りたい場合は、バンドルアナライザーが有効です。
Next.js の場合:
npm install --save-dev @next/bundle-analyzernext.config.js に設定を追加して ANALYZE=true npm run build を実行すると、ブラウザで依存関係のサイズをビジュアルで確認できます。
削ったときどれくらい減るかが見えると、削る優先度をつけやすくなります。
サイズが大きくて使っていないものから手をつけると、効果を実感しやすい。
moment はバンドルサイズが大きい代表格です。
ロケール情報を含めると 300KB 近くになることがあるので、使っていないなら早めに dayjs へ移行することをおすすめします。
実際に削ったときの失敗談と学び
判断基準を持っても、失敗はありました。
moment を削除した後、日付処理が別ファイルに残っていることに気づいたのです。
src/utils/date.ts に moment を使っている処理があったのに、grep のパスを src/components/ だけに絞っていて見逃していた。
ビルドは通った(TypeScript の型エラーにはならなかった)のに、実行時にエラーが出てから気づきました。
📌 教訓
削除前は必ずプロジェクト全体を検索する
# src/ だけでなくプロジェクト全体
grep -r "from 'moment'" ./ --include="*.ts" --include="*.tsx"また、moment を削除する際に dayjs への移行も同時対応が必要でした。
単純に削除するだけでなく、代替をどうするかまで考えておくことが、スムーズな整理につながります。
整理した後の変化
ESLint から Biome に移行したとき、eslint-plugin-* 系のプラグインを一気に削除しました。
体感として変わったこと:
npm install の速度:
半分以下になった感覚(node_modules のサイズが目に見えて減った)
CI のキャッシュヒット率:
依存が減った分、キャッシュがより効くようになった
認知コスト:
久しぶりにプロジェクトを開いたとき「これ何だっけ?」がなくなった
npm audit の出力:
使っていないパッケージの脆弱性アラートがなくなり、本当に対応すべきものが見やすくなった
フリーランスで複数案件を並行していると、数ヶ月ぶりに開いたプロジェクトが定期的に来ます。
そのとき package.json がすっきりしているかどうかで、再起動のコストが大きく変わります。
自分が使っているものだけが並んでいる package.json は、それ自体がドキュメントになるのです。
削るだけでなく、 入れ替えることも視野に
整理の過程で単純に削除するだけでなく、より軽いものに入れ替える選択肢も見えてきます。
代表的な例:

| 削除候補 | 入れ替え候補 | 理由 |
|:---|:---|:---|
| moment | dayjs | バンドルサイズが約 1/40(dayjs は約 2 KB)|
| lodash | ネイティブ JavaScript(Vanilla JS) | ES2020 以降は多くの lodash 関数が不要 |
| axios | fetch (ネイティブ) | Next.js App Router では拡張 fetch が使える |
| classnames | clsx + tailwind-merge | Tailwind CSS 使用なら専用ツールの方が便利 |このような削って入れ替える判断は、単純な大掃除ではなくコードベースを今のエコシステムに合わせていくプロセスでもあります。
入れ替えを 1 回で全部やろうとすると大変なので、整理のたびに 1〜2 個を見直すという習慣でも十分です。
AI セルフレビューへの組み込み
最近は、コードレビューを Cursor(AI)と行うフローに package.json の確認も組み込んでいます。
PR を作る前のチェックリストに以下を追加しました:
📍 この PR で新たに追加したライブラリは本当に必要か?
📍 既存のライブラリや標準 API で代替できないか?
📍 devDependencies と dependencies の区別は正しいか?
📍 そのライブラリは今後もメンテナンスされ続けるか?
(GitHub の最終コミット日・スター数を確認)
「レビュアーがいない僕が AI と自分レビューの型を作った話」でも書きましたが、ひとりで品質を守るには自分で質問する仕組みが必要です。
package.json の見直しも同じです。
定期的にチェックするのではなく、PR 単位でチェックする習慣にすることで、膨らみを入口で防ぐことができます。
削る作業は後からでもできますが、入れる前に一度考えることが膨らみの予防になります。
フリーランス・個人開発者はレビュアーがいないからこそ、こういった自分で質問する仕組みが品質を守る設計の一部になるのです。
定期メンテナンスの習慣化
depcheck を定期的に実行するタイミングとして、僕が使っているのは 2 つです。
1️⃣ 月初のプロジェクト振り返り(週次レビューの延長)
GTD の週次レビューで「今週使ったツール・ライブラリは何か?」を振り返るついでに、depcheck を実行します。
月に一度、コードベースの棚卸しをするイメージです。
2️⃣ 依存関係の更新(npm update)のタイミング
バージョンを上げる際に、合わせて「これは本当に必要か?」を確認します。
更新して動かなくなるリスクを取るより、使っていないなら削除したほうがシンプルです。
この 2 つを組み合わせることで、年末の大掃除ではなく日常の小掃除として package.json を管理できるようになりました。
フリーランスとして感じる、 依存関係への向き合い方
個人開発をしていると、ライブラリの選択は自分一人で決める。
入れるのも、削るのも、更新するのも——全部、自分の判断です。
チームで開発していれば、「このライブラリはなぜ入れたの?」とレビューで聞いてもらえる。
ひとりだと、そのチェックが入らない。
だから package.json が膨らみやすいのは、怠慢ではなく構造的な問題だと思っています。
吃音症と向き合ってきた経験から、予期しない状況をできるだけ減らすことが僕にとって大切だと分かっています。
コードベースでも同じで、見覚えのないライブラリが並んでいる状態は、予期しないエラーの温床になる。
だから、package.json を整理することは、単なる掃除ではなく——予期しない状況を減らすための設計だと捉えています。
複数案件を並行するフリーランスとして、プロジェクトを久しぶりに開いたときの認知コストを下げることは、直接、仕事の効率と心理的な安定につながります。
今の自分が使っているものだけが並んでいる package.json は、それ自体が信頼できるドキュメントになる——そう実感するようになりました。
今の自分に必要かで整理する
package.json の整理は技術的な作業ですが、発想は服の断捨離と同じです。
使わないライブラリを見極める 3 つの判断基準:
1️⃣ 直接 import しているか
(grep で全体検索)
2️⃣ 間接依存か直接依存か
(npm ls で確認)
3️⃣ セキュリティ警告があるか
(npm audit で確認)
この 3 つで整理したあと、depcheck を定期的に実行することで膨らみを早期に発見できます。
整理の実作業フローをまとめると、こうなります:

| ステップ | コマンド | 確認内容 |
|:---|:---|:---|
| 1. 未使用の洗い出し | npx depcheck | import されていないパッケージを検出 |
| 2. 依存ツリーの確認 | npm ls <パッケージ名> | 直接依存か間接依存かを分ける |
| 3. セキュリティ確認 | npm audit | 脆弱性のあるパッケージを優先削除 |
| 4. サイズの可視化 | bundle analyzer | 削除効果が大きいものを把握 |
| 5. 全体検索してから削除 | grep -r "from 'パッケージ名'" ./ | 見逃しを防ぐ |大掃除は年末だけではありません。
梅雨前の今、コードベースも「今の自分に必要か?」で見直してみませんか。
使わないライブラリは、放置するほど削りにくくなります。
でも、3 つの基準を持てば、今日の 15 分で始められる。
今日の小掃除が、3 ヶ月後の自分への贈り物になるはずです。
ひとりごと
「これ何のために入れたんだっけ」と思いながら放置し続けた時期があった。
削る勇気がなかったのではなく、削る基準がなかっただけだった——と気づいたのは、depcheck を初めて実行したときでした。
技術の整理も、服の断捨離も、発想は同じです。
「今の自分に必要か」で問えば、答えは意外とすぐ出てくる。
みなさんの package.json にも、今日手放せるものがあるかもしれません。

Substack はじめました
ここまで読んでくださり、ありがとうございました。
X では短い言葉で、note では整理した文章で発信していますが、Substack では、もっと途中経過の思考や削りきらなかった葛藤、技術者として日々考えていることを書いています。
もし興味があれば、覗いてみてください。
会社員(元システムエンジニア)からフリーランスとなり、
15 年目に突入しました。
納期と障害対応に追われる毎日の中で、
「もっと自由に、もっと本質的にものづくりがしたい」
そう思ったのが独立のきっかけです。
現在は、技術と文章を軸に、
仕事がラクになる仕組みや続けられる働き方を発信しています。
【フリーランスになって15年目突入】
— おおとろ|フリーランス開発者 × ストーリーテラー (@digiangler) March 3, 2026
14年という月日は長いようで、
あっという間だった。
成功したと言えるほどの派手さはないけれど、
今日までエンジニアとしてご飯を食べ、
新しいコードを書けている。
それだけで十分幸せなことなんだと思う。
明日は明日で、また淡々と、…
あわせて読みたい
▼ 依存関係を更新する判断基準まで深めたいときに
削る判断基準を持ったら、次は上げる判断基準へ。
止まった依存関係に静かな利息がつく怖さと、触ってよい条件を言語化するプロセスを書いています。
セットで読むと依存関係への向き合い方が整います。
▼ ESLint 系プラグインをまとめて削除した実体験を読みたいときに
eslint-plugin-* を一気に削除して npm install が劇的に速くなった記録。
使わないライブラリを削る体験の最大の実例として、Biome 移行の全プロセスを公開しています。
▼ 入れる前に考えることをコードレビューに組み込みたいときに
ひとり開発者が品質を守るための AI セルフレビューの型。
「この PR で新たに追加したライブラリは本当に必要か?」をチェックリストに組み込む発想のベースになる記録です。
次の一歩を一緒に決める作戦会議室へ
「自分のプロジェクトの依存関係を整理したいけど、どこから手をつけていいか分からない」
——そんな方へ。
フリーランス開発者の作戦会議室では、package.json の整理・Biome 移行・AI セルフレビューの型など、個人開発の品質を一人で守るための実践を小さく分け合っています。
「自分のプロジェクトに当てはめるとどうなる?」という具体的な相談も持ち込んでください。

ここから先は
最後まで読んでいただき、ありがとうございます。もしこの記事が「役に立った」「心に響いた」と感じたら、珈琲一杯分サポートいただけると嬉しいです。あなたの温かい応援を力に、また次の創作活動に励みます。
