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必須 |
|---|---|---|
es | ESM対応環境(推奨デフォルト) | 不要 |
cjs | Node.js(CommonJS) | 不要 |
umd | ブラウザ+Node.js汎用 | 必須 |
iife | ブラウザ<script>タグ | 必須 |
amd | RequireJS等 | 不要 |
system | SystemJS | 不要 |
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-resolve | node_modulesのパッケージ解決 |
@rollup/plugin-commonjs | CJS→ESM変換 |
@rollup/plugin-typescript | TypeScriptコンパイル |
@rollup/plugin-terser | コード圧縮(minify) |
@rollup/plugin-json | JSONインポート |
@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();
}
類似パッケージとの比較
| 特徴 | Rollup | webpack | esbuild | Vite |
|---|---|---|---|---|
| 主な用途 | ライブラリ | アプリケーション | 汎用(高速) | アプリケーション |
| Tree Shaking | ◎ 最も優秀 | ○ 良好 | ○ 良好 | ◎(内部でRollup使用) |
| ビルド速度 | ○ | △ | ◎ 最速 | ◎(esbuild+Rollup) |
| ESM対応 | ◎ ネイティブ | ○ | ◎ | ◎ |
| コード分割 | ○ | ◎ | △ | ◎ |
| プラグイン数 | 豊富 | 最も豊富 | 少なめ | 豊富(Rollup互換) |
| 設定の複雑さ | シンプル | 複雑 | 最もシンプル | シンプル |
| HMR(開発サーバー) | なし | あり | なし | あり |
| 言語 | Rust+JS | JS | Go | JS |
選定の目安:
- ライブラリ開発 → 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"を設定してください。