コンテンツへスキップ

Rollup と他のツールの統合

NPM パッケージとの統合

プロジェクトが `node_modules` フォルダーにインストールされたパッケージに依存するようになる可能性があります。Webpack や Browserify などの他のバンドラーとは異なり、Rollup はこれらの依存関係を「すぐに」処理する方法を知りません。設定を追加する必要があります。

人生、宇宙、そして万物についての究極の答えをエクスポートする、the-answer という単純な依存関係を追加してみましょう。

シェル
npm install the-answer
# or `npm i the-answer`

`src/main.js` ファイルを更新した場合…

js
// src/main.js
import answer from 'the-answer';

export default function () {
	console.log('the answer is ' + answer);
}

…そして Rollup を実行すると…

シェル
npm run build

…このような警告が表示されます。

(!) Unresolved dependencies
https://github.com/rollup/rollup/wiki/Troubleshooting#treating-module-as-external-dependency
the-answer (imported by main.js)

`import`宣言は CommonJS の `require` ステートメントに変換されるため、結果として得られる `bundle.js` は Node.js で動作しますが、`the-answer` はバンドルに含まれません。そのためには、プラグインが必要です。

@rollup/plugin-node-resolve

@rollup/plugin-node-resolve プラグインは、Rollup に外部モジュールの検索方法を教えます。インストールするには…

シェル
npm install --save-dev @rollup/plugin-node-resolve

…そして設定ファイルに追加します。

js
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';

export default {
	input: 'src/main.js',
	output: {
		file: 'bundle.js',
		format: 'cjs'
	},
	plugins: [resolve()]
};

今度は、`npm run build` を実行しても警告は表示されません。バンドルにはインポートされたモジュールが含まれています。

@rollup/plugin-commonjs

一部のライブラリは、そのままインポートできる ES モジュールを公開しています。`the-answer` はそのようなモジュールの1つです。しかし現時点では、NPM のパッケージの大部分は CommonJS モジュールとして公開されています。それが変わるまでは、Rollup が処理できるようになる前に、CommonJS を ES2015 に変換する必要があります。

@rollup/plugin-commonjs プラグインはまさにそれを行います。

ほとんどの場合、`@rollup/plugin-commonjs` はモジュールを変換する他のプラグインの*前*に配置する必要があります。これは、他のプラグインが CommonJS の検出を妨げる変更を加えるのを防ぐためです。このルールの例外は Babel プラグインです。Babel プラグインを使用している場合は、commonjs プラグインの前に配置してください。

ピア依存関係

React や Lodash など、ピア依存関係を持つライブラリを構築しているとしましょう。上記のように externals を設定すると、rollup はすべてのインポートをバンドルします。

js
import answer from 'the-answer';
import _ from 'lodash';

バンドルするインポートと外部として扱うインポートを細かく調整できます。この例では、`lodash` を外部として扱い、`the-answer` は外部として扱いません。

設定ファイルは次のとおりです。

js
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';

export default {
	input: 'src/main.js',
	output: {
		file: 'bundle.js',
		format: 'cjs'
	},
	plugins: [
		resolve({
			// pass custom options to the resolve plugin
			moduleDirectories: ['node_modules']
		})
	],
	// indicate which modules should be treated as external
	external: ['lodash']
};

これで、`lodash` は外部として扱われ、ライブラリにバンドルされなくなります。

`external` キーには、モジュール名の配列、またはモジュール名を受け取り、外部として扱う必要がある場合は true を返す関数のいずれかを指定できます。例えば

js
export default {
	// ...
	external: id => /lodash/.test(id)
};

babel-plugin-lodash を使用して `lodash` モジュールを選択的に取り込んでいる場合、この形式を使用する場合があります。この場合、Babel はインポートステートメントを次のように変換します。

js
import _merge from 'lodash/merge';

`external` の配列形式はワイルドカードを処理しないため、このインポートは関数形式でのみ外部として扱われます。

Babel

多くの開発者は、ブラウザと Node.js でまだサポートされていない最新の JavaScript 機能を使用するために、プロジェクトでBabel を使用しています。

Babel と Rollup の両方を使用する最も簡単な方法は、@rollup/plugin-babel を使用することです。まず、プラグインをインストールします。

シェル
npm i -D @rollup/plugin-babel @rollup/plugin-node-resolve

`rollup.config.js` に追加します。

js
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import babel from '@rollup/plugin-babel';

export default {
	input: 'src/main.js',
	output: {
		file: 'bundle.js',
		format: 'cjs'
	},
	plugins: [resolve(), babel({ babelHelpers: 'bundled' })]
};

Babel が実際にコードをコンパイルする前に、設定する必要があります。新しいファイル `src/.babelrc.json` を作成します。

json
{
	"presets": ["@babel/env"]
}

プロジェクトルートではなく、`src` に ` .babelrc.json` ファイルを配置しています。これにより、後で必要になった場合に、テストなどに対して別の `.babelrc.json` を持つことができます。プロジェクト全体の構成とファイル相対の構成の両方の詳細については、Babel のドキュメント を参照してください。

これで、rollup を実行する前に、`babel-core``env` プリセットをインストールする必要があります。

シェル
npm i -D @babel/core @babel/preset-env

これで Rollup を実行するとバンドルが作成されますが、実際には ES2015 の機能は使用していません。`src/main.js` を編集して変更しましょう。

js
// src/main.js
import answer from 'the-answer';

export default () => {
	console.log(`the answer is ${answer}`);
};

`npm run build` で Rollup を実行し、バンドルを確認します。

js
'use strict';

var index = 42;

var main = function () {
	console.log('the answer is ' + index);
};

module.exports = main;

Gulp

Rollup は gulp が理解できる Promise を返すため、統合は比較的簡単です。

構文は設定ファイルと非常によく似ていますが、プロパティは JavaScript API に対応する2つの異なる操作に分割されています。

js
const gulp = require('gulp');
const rollup = require('rollup');
const rollupTypescript = require('@rollup/plugin-typescript');

gulp.task('build', () => {
	return rollup
		.rollup({
			input: './src/main.ts',
			plugins: [rollupTypescript()]
		})
		.then(bundle => {
			return bundle.write({
				file: './dist/library.js',
				format: 'umd',
				name: 'library',
				sourcemap: true
			});
		});
});

`async/await` 構文を使用することもできます。

js
const gulp = require('gulp');
const rollup = require('rollup');
const rollupTypescript = require('@rollup/plugin-typescript');

gulp.task('build', async function () {
	const bundle = await rollup.rollup({
		input: './src/main.ts',
		plugins: [rollupTypescript()]
	});

	await bundle.write({
		file: './dist/library.js',
		format: 'umd',
		name: 'library',
		sourcemap: true
	});
});

Deno

Deno で Rollup を実行したい場合は、次のように esm.sh を使用できます。

js
import { rollup } from "https://esm.sh/@rollup/browser";

const bundle = await rollup({ //...

しかし、複雑なコンパイルには適していません。代わりに、npm から rollup をインストールすることもできます。

js
import { rollup } from "npm:rollup";

const bundle = await rollup({ //...

注意: Rollup を実行すると、Deno はいくつかの権限を要求します。

MIT ライセンスの下でリリースされています。