😸

npm、npx、bunの使い分け:実践ガイド

2025/03/14に公開

はじめに

JavaScriptの開発環境では、npmnpxbunなどのツールを日常的に使用しています。

しかし、これらの違いや適切な使い分けについて、明確に理解している開発者は意外と少ないかもしれません。

特にnode_modulesフォルダの肥大化や、似たようなコマンドの混在に悩んだ経験はありませんか?

この記事では、これらのツールの仕組みと適切な使い分けについて、実際のユースケースに基づいて解説します。

ツールの仕組みを理解する

npm(Node Package Manager)

npmはNode.jsのパッケージ管理システムで、以下の特徴があります:

  • パッケージの保存場所node_modulesフォルダ(プロジェクトローカルまたはグローバル)
  • 設定ファイルpackage.json(依存関係の一覧)とpackage-lock.json(正確なバージョン情報)
  • 主な用途:パッケージのインストール、更新、削除、スクリプトの実行
# パッケージをインストール
npm install react

# 開発用パッケージをインストール
npm install --save-dev typescript

# グローバルにインストール
npm install -g typescript

# スクリプトを実行
npm run build

npx(Node Package Execute)

npxはnpmに含まれるツールで、パッケージを一時的に実行するために使用します:

  • 検索順序

    1. ローカルのnode_modules/.binディレクトリ
    2. グローバルにインストールされたパッケージ
    3. npmレジストリ(オンライン)から一時的にダウンロード
  • 主な用途

    • インストールせずにパッケージを一時的に実行
    • ローカルにインストールされたツールを簡単に実行
    • 特定バージョンのツールを試す
# create-react-appを一時的に実行(インストールなし)
npx create-react-app my-app

# ローカルにインストールされたeslintを実行
npx eslint .

# 特定バージョンを指定して実行
npx typescript@4.5.5 tsc --version

bun

bunは新しいJavaScript/TypeScriptランタイムとパッケージマネージャーで、高速な処理が特徴です:

  • パッケージの保存場所node_modulesフォルダ(最適化されたバイナリキャッシュも使用)
  • 設定ファイルpackage.jsonbun.lockb(バイナリ形式のロックファイル)
  • 主な用途:高速なパッケージ管理、JavaScriptの実行、ビルド、テスト
# パッケージをインストール(npmより高速)
bun install

# JavaScriptやTypeScriptを直接実行
bun index.ts

# 開発サーバーを起動(ホットリロード付き)
bun --hot index.ts

# テストを実行
bun test

ユースケース別の使い分け

1. GitHubから他人のリポジトリを一度だけ試す場合

基本的なアプローチ

# リポジトリをクローン
git clone https://github.com/username/repository.git
cd repository

# 依存関係をインストール
npm install  # または bun install(高速)

# 実行
npm run dev  # または bun run dev

ツールの選択ポイント

  • npm:互換性を重視する場合
  • bun:速度を重視する場合(特に大規模プロジェクト)
  • npx:プロジェクト内のツールを実行する場合(例:npx jest

実際の例

# Reactプロジェクトを試す場合
git clone https://github.com/facebook/create-react-app.git
cd create-react-app
npm install
cd packages/cra-template
npm run start

# プロジェクト内のツールを実行
npx jest  # ローカルのnode_modules/.binからjestを探して実行

ここでのポイントは、npxがまずローカルのnode_modules/.binを探すという点です。プロジェクトにインストールされたツールを簡単に実行できます。

2. 新しいプロジェクトを作成する場合

基本的なアプローチ

# Reactプロジェクトを作成
npx create-react-app my-app

# または Next.jsプロジェクトを作成
npx create-next-app my-next-app

# または Viteプロジェクトを作成
npx create-vite my-vite-app

ツールの選択ポイント

  • npx:一度だけ使うツールに最適(プロジェクト作成ツールなど)
  • bunx:高速な実行が必要な場合(bunxnpxの高速版)

実際の例

# TypeScriptを使ったReactプロジェクトを作成
npx create-react-app my-app --template typescript

# 作成したプロジェクトに移動
cd my-app

# 開発サーバーを起動
npm start

ここでのポイントは、npxがオンラインからツールを一時的にダウンロードして実行するという点です。

プロジェクト作成後は不要になるツールなので、インストールする必要がありません。

3. 本番開発で継続的に使用する場合

基本的なアプローチ

# プロジェクト初期化
npm init -y

# 必要なパッケージをインストール
npm install react react-dom
npm install --save-dev typescript @types/react

# package.jsonにスクリプトを追加
# "scripts": {
#   "start": "react-scripts start",
#   "build": "react-scripts build",
#   "test": "react-scripts test"
# }

# 開発
npm run start

ツールの選択ポイント

  • npm:安定性と互換性を重視する場合
  • bun:開発速度を重視する場合
  • npx:ローカルツールの実行や特定バージョンのテストに

実際の例

# 開発中にTypeScriptの特定バージョンを試す
npx typescript@4.5.5 tsc --version

# ローカルにインストールされたESLintを実行
npx eslint src/ --fix

# 本番ビルド
npm run build

ここでのポイントは、npmでプロジェクトの依存関係を管理しつつ、npxで特定のツールを柔軟に実行できるという点です。

node_modulesの管理と最適化

問題点

  • node_modulesフォルダは非常に大きくなる(数GB)
  • 同じパッケージの複数バージョンが含まれることがある
  • プロジェクト間で重複するパッケージが多い

解決策

  1. Gitから除外する

    # .gitignore
    node_modules/
    
  2. 定期的に整理する

    # 不要なパッケージを削除
    npm prune
    
    # キャッシュをクリアする
    npm cache clean --force
    
  3. bunを使用して効率化

    # npmの代わりにbunを使用
    bun install
    

    bunは依存関係をより効率的に管理し、インストール速度も大幅に向上します。

  4. pnpmの使用を検討

    # pnpmをインストール
    npm install -g pnpm
    
    # pnpmでインストール
    pnpm install
    

    pnpmはシンボリックリンクを使用して、パッケージを共有ストレージに保存します。

npxの高度な使い方

特定バージョンの実行

# TypeScriptの特定バージョンを実行
npx typescript@4.5.5 tsc --version

# Reactの古いバージョンのcreate-react-appを使用
npx create-react-app@4.0.0 my-old-app

オプションの活用

# ローカルとグローバルのみを使用(オンラインからダウンロードしない)
npx --no-install eslint .

# ローカルとグローバルを無視して常に最新をダウンロード
npx --ignore-existing create-react-app my-app

GitHubリポジトリから直接実行

# GitHubのリポジトリから直接実行
npx github:user/repo

# または
npx https://github.com/user/repo/archive/main.tar.gz

チーム開発での使い分け

複数のツールが混在する場合

  1. package.jsonでスクリプトを統一

    "scripts": {
      "start": "react-scripts start",
      "build": "react-scripts build",
      "test": "react-scripts test"
    }
    

    これにより、npm、yarn、bunのどれを使っても同じコマンドで実行できます。

  2. CIパイプラインでの実行環境を固定

    # GitHub Actions例
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
      - run: npm ci
      - run: npm test
    
  3. チームでのルールを決める

    • 開発環境:個人の好みのツール(npm/bun/pnpm)を使用可
    • CI/CD:特定のツール(例:npm)に統一
    • lockファイル:どのファイルを優先するか決める

まとめ:状況別おすすめツール

一度だけ使うツール

  • ベストチョイス: npx
  • 使用例: npx create-react-app my-app
  • 理由: インストール不要で一時的に実行できる

プロジェクトの依存関係管理

  • 安定性重視: npm
  • 速度重視: bun
  • ディスク容量重視: pnpm
  • 使用例: npm install / bun install / pnpm install

ローカルツールの実行

  • ベストチョイス: npx
  • 使用例: npx eslint .
  • 理由: パスを指定せずに簡単に実行できる

高速な開発環境

  • ベストチョイス: bun
  • 使用例: bun --hot index.ts
  • 理由: 高速な実行とホットリロード

大規模プロジェクト

  • ベストチョイス: bun または pnpm
  • 使用例: bun install / pnpm install
  • 理由: 効率的な依存関係管理と高速なインストール

最終的な選択

これらのツールは、それぞれ異なる目的と強みを持っています。重要なのは、プロジェクトの要件や状況に応じて適切に使い分けることです。

  • npm: 安定性と互換性を重視する場合
  • npx: 一時的な実行や特定バージョンのテストに
  • bun: 高速な開発環境と効率的な依存関係管理に

これらを適切に組み合わせることで、より効率的なJavaScript/TypeScript開発が可能になります。

Discussion