rollup の使い方

Next-generation ES module bundler

v4.60.1/週MITビルドツール
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

Rollup の使い方 — 次世代ESモジュールバンドラー完全ガイド

一言でいうと

RollupはESモジュール(ES2015+のimport/export)を基盤とするJavaScriptモジュールバンドラーです。強力なTree Shaking機能により、使われていないコードを自動的に除去し、軽量で最適化されたバンドルを生成します。

どんな時に使う?

  • ライブラリの公開 — npm向けにESM/CJS/UMD形式のパッケージを配布したいとき。Rollupはライブラリバンドルにおいて事実上のスタンダードです
  • Tree Shakingを最大限に活かしたい — バンドルサイズを極限まで小さくしたいプロジェクトで、未使用コードを確実に除去したいとき
  • ESモジュール形式の出力が必要 — モダンブラウザ向けに最適化されたESM形式のバンドルを生成したいとき

インストール

# npm
npm install --save-dev rollup

# yarn
yarn add --dev rollup

# pnpm
pnpm add --save-dev rollup

# グローバルインストール(CLIとして使う場合)
npm install --global rollup

※ 本記事はRollup v4.60.1時点の情報に基づいています。

Rollup の基本的な使い方

プロジェクト構成

my-lib/
├── src/
│   ├── index.ts
│   └── utils.ts
├── rollup.config.mjs
├── package.json
└── tsconfig.json

設定ファイル(rollup.config.mjs)

// rollup.config.mjs
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

/** @type {import('rollup').RollupOptions} */
export default {
  input: 'src/index.ts',
  output: [
    {
      file: 'dist/index.cjs.js',
      format: 'cjs',
      sourcemap: true,
    },
    {
      file: 'dist/index.esm.js',
      format: 'es',
      sourcemap: true,
    },
  ],
  plugins: [
    resolve(),
    commonjs(),
    typescript({ tsconfig: './tsconfig.json' }),
  ],
};

ソースコード例

// src/utils.ts
export function add(a: number, b: number): number {
  return a + b;
}

export function subtract(a: number, b: number): number {
  return a - b;
}

// この関数はindex.tsでimportされないため、Tree Shakingで除去される
export function unusedFunction(): void {
  console.log('This will be removed from the bundle');
}
// src/index.ts
export { add, subtract } from './utils';

ビルド実行

# 設定ファイルを使ってビルド
npx rollup --config rollup.config.mjs

# watchモード
npx rollup --config rollup.config.mjs --watch

package.jsonにスクリプトを追加しておくと便利です。

{
  "name": "my-lib",
  "main": "dist/index.cjs.js",
  "module": "dist/index.esm.js",
  "exports": {
    ".": {
      "import": "./dist/index.esm.js",
      "require": "./dist/index.cjs.js"
    }
  },
  "scripts": {
    "build": "rollup --config rollup.config.mjs",
    "dev": "rollup --config rollup.config.mjs --watch"
  }
}

よく使うAPI・設定オプション

1. output.format — 出力形式の指定

Rollupは複数の出力形式をサポートしています。

// rollup.config.mjs
export default {
  input: 'src/index.ts',
  output: [
    // ESモジュール形式(モダンブラウザ・バンドラー向け)
    { file: 'dist/index.esm.js', format: 'es' },

    // CommonJS形式(Node.js向け)
    { file: 'dist/index.cjs.js', format: 'cjs' },

    // UMD形式(ブラウザ・Node.js両対応)
    { file: 'dist/index.umd.js', format: 'umd', name: 'MyLib' },

    // IIFE形式(<script>タグで直接読み込む用)
    { file: 'dist/index.iife.js', format: 'iife', name: 'MyLib' },
  ],
};
format用途name必須
esESM対応環境(推奨デフォルト)不要
cjsNode.js(CommonJS)不要
umdブラウザ+Node.js汎用必須
iifeブラウザ<script>タグ必須
amdRequireJS等不要
systemSystemJS不要

2. external — 外部依存の除外

ライブラリをバンドルする際、dependenciesに含まれるパッケージはバンドルに含めないのが一般的です。

// rollup.config.mjs
import { readFileSync } from 'node:fs';

const pkg = JSON.parse(readFileSync('./package.json', 'utf-8'));

export default {
  input: 'src/index.ts',
  output: { file: 'dist/index.esm.js', format: 'es' },
  // dependencies と peerDependencies を自動的に external に設定
  external: [
    ...Object.keys(pkg.dependencies || {}),
    ...Object.keys(pkg.peerDependencies || {}),
  ],
};

正規表現やコールバック関数も使えます。

export default {
  // ...
  external: [
    /^node:/,                    // Node.js組み込みモジュール
    /^@my-org\//,                // 特定スコープのパッケージ
    (id) => id.includes('lodash'), // カスタムロジック
  ],
};

3. JavaScript API — プログラムからの実行

CLIではなく、Node.jsスクリプトからRollupを呼び出すことも可能です。

// scripts/build.ts
import { rollup, watch, type RollupOptions, type OutputOptions } from 'rollup';
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';

async function build() {
  const inputOptions: RollupOptions = {
    input: 'src/index.ts',
    plugins: [resolve(), typescript()],
  };

  const outputOptions: OutputOptions = {
    file: 'dist/index.esm.js',
    format: 'es',
    sourcemap: true,
  };

  // バンドルを作成
  const bundle = await rollup(inputOptions);

  // バンドル内のモジュール一覧を確認
  console.log('Modules:', bundle.watchFiles);

  // ファイルに書き出し
  await bundle.write(outputOptions);

  // リソースを解放
  await bundle.close();
}

build().catch(console.error);

4. plugins — プラグインシステム

Rollupの機能拡張はプラグインで行います。公式プラグイン(@rollup/plugin-*)が豊富に用意されています。

// rollup.config.mjs
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import terser from '@rollup/plugin-terser';
import json from '@rollup/plugin-json';
import replace from '@rollup/plugin-replace';

export default {
  input: 'src/index.ts',
  output: { file: 'dist/index.esm.js', format: 'es' },
  plugins: [
    // node_modules内のパッケージを解決
    resolve({ browser: true }),

    // CommonJSモジュールをESMに変換
    commonjs(),

    // TypeScriptのコンパイル
    typescript(),

    // JSONファイルのインポートを可能に
    json(),

    // 環境変数の置換
    replace({
      preventAssignment: true,
      'process.env.NODE_ENV': JSON.stringify('production'),
    }),

    // 本番ビルド時のみminify
    process.env.NODE_ENV === 'production' && terser(),
  ],
};

主要な公式プラグイン一覧:

プラグイン用途
@rollup/plugin-node-resolvenode_modulesのパッケージ解決
@rollup/plugin-commonjsCJS→ESM変換
@rollup/plugin-typescriptTypeScriptコンパイル
@rollup/plugin-terserコード圧縮(minify)
@rollup/plugin-jsonJSONインポート
@rollup/plugin-replace文字列置換
@rollup/plugin-aliasモジュールエイリアス
@rollup/plugin-image画像ファイルのインポート

5. 複数エントリーポイントとコード分割

// rollup.config.mjs
export default {
  // 複数エントリーポイント
  input: {
    index: 'src/index.ts',
    utils: 'src/utils.ts',
    constants: 'src/constants.ts',
  },
  output: {
    dir: 'dist',          // 複数出力時は file ではなく dir を使う
    format: 'es',
    entryFileNames: '[name].js',
    chunkFileNames: 'chunks/[name]-[hash].js',
    sourcemap: true,
  },
  plugins: [/* ... */],
};

動的インポートによる自動コード分割も可能です。

// src/index.ts
export async function loadHeavyModule() {
  // Rollupが自動的に別チャンクに分割する
  const { heavyFunction } = await import('./heavy-module');
  return heavyFunction();
}

類似パッケージとの比較

特徴RollupwebpackesbuildVite
主な用途ライブラリアプリケーション汎用(高速)アプリケーション
Tree Shaking◎ 最も優秀○ 良好○ 良好◎(内部でRollup使用)
ビルド速度◎ 最速◎(esbuild+Rollup)
ESM対応◎ ネイティブ
コード分割
プラグイン数豊富最も豊富少なめ豊富(Rollup互換)
設定の複雑さシンプル複雑最もシンプルシンプル
HMR(開発サーバー)なしありなしあり
言語Rust+JSJSGoJS

選定の目安:

  • ライブラリ開発Rollup(Tree Shakingの品質、ESM出力の最適化が最良)
  • Webアプリ開発Vite(内部でRollupを使用、開発体験が優秀)
  • ビルド速度最優先esbuild(ただしプラグインエコシステムは限定的)
  • 複雑なアプリ・レガシー対応webpack(最も柔軟だが設定が複雑)

注意点・Tips

1. CommonJSモジュールの扱いに注意

Rollupは本質的にESモジュールバンドラーです。CommonJSモジュール(require/module.exports)を使うには@rollup/plugin-commonjs必須です。

// ❌ これだけではnode_modulesのCJSパッケージを読み込めない
plugins: [resolve()]

// ✅ commonjsプラグインを必ず追加
plugins: [resolve(), commonjs()]

2. externalの設定忘れに注意

ライブラリをバンドルする際、依存パッケージをexternalに指定しないと、それらがバンドルに含まれてしまいます。利用者側で重複が発生し、バンドルサイズが肥大化する原因になります。

// ❌ reactがバンドルに含まれてしまう
export default {
  input: 'src/index.ts',
  output: { file: 'dist/index.js', format: 'es' },
};

// ✅ peerDependenciesは必ずexternalに
export default {
  input: 'src/index.ts',
  output: { file: 'dist/index.js', format: 'es' },
  external: ['react', 'react-dom'],
};

3. 設定ファイルの拡張子

Rollup v4では設定ファイルにESM構文(export default)を使う場合、ファイル名をrollup.config.mjsにするか、package.json"type": "module"を設定してください。

4. preserveModulesでディレクトリ