イマドキは Webpack じゃなくて Rollup だ!Terser とともに Rollup を使ってみる
Webpack なんかと同じビルド・バンドルツールの Rollup を使ってみる。
目次
- Rollup と Webpack の違い
- Transpiler と Minifier との区別
- Rollup を試してみる
- Rollup の設定ファイルを作る
- Terser を組み込む :
rollup-plugin-terser
Rollup と Webpack の違い
同じバンドルツールである Webpack と Rollup の特徴を比べてみる。
- 参考 : WebpackとRollupを比べてみて - Qiita
- CommonJS :
require
とmodule.exports
- ES6 (ES2015) :
import
とexport
- Webpack は CommonJS しか認識できない
- CommonJS :
- 参考 : webpackとRollup : 似て非なるもの | POSTD
- Rollup は ES2015 のモジュールの仕組みを活かす作り
- ライブラリには Rollup が向いている
- 参考 : Rollupがちょうどいい感じ - Qiita
- Rollup は内部的に ES6 で扱う
- 参考 : rollup が求めてたものだったかもしれない
- Export のフォーマット別比較
Webpack は CommonJS で認識し、Rollup は ES Modules で扱う、というのが大きな違いか。ECMAScript のバージョンの違いだけでなく、コレが Tree-Shaking などに効いてくるので、バンドル効率に差が出てくるようだ。
Transpiler と Minifier との区別
Rollup や Webpack は Bundler であるが、Babel は Transpiler だし、後で使う Terser は Minifier だ。これらの区別をしっかり付けておこう。
- Bundler
export
・import
で複数に別れているファイルたちを1ファイルに束ねる
- Transpiler
- 新しい仕様のコードを古い仕様のコードに変換する
- Minifier
- コードを圧縮したり難読化したりする
素人考えだと「Bundler で束ねて → Transpiler で形式直して → Minifier で圧縮すればええんちゃうの?」と思ってしまうが、実際のところはそう簡単にもいかないようだ。
何を付け足し、何を取り除いていいか、という判断が複雑になり、Source Map を作るのが困難だったりするらしい。
その辺を解消するために、Webpack や Rollup はプラグインという形で、Babel や Terser を組み込めるようにしているようだ。
Rollup を試してみる
概念を整理したところで、Rollup を使ってみる。公式のガイドを参考に。
- 参考 : rollup.js
適当な作業用ディレクトリを作り、rollup
コマンドがローカルで動くことを確認する。
$ npm init -y
$ npm install -D rollup
$ npx rollup
そしたら次のようなファイルを作ってみる。
src/index.mjs
import hoge from './hoge.mjs';
import fuga from './fuga.mjs';
new hoge().hello();
console.log(fuga);
src/hoge.mjs
export default class hoge {
hello() {
console.log('Hello');
}
}
src/fuga.mjs
const fuga = {
a: 'a',
b: 'b'
};
export default fuga;
ES Modules の仕組みで実装しているので、拡張子は .mjs
で、require
ではなく import
を使っている。
コレを Rollup で束ねてみる。
$ npx rollup src/index.mjs
src/index.mjs → stdout...
class hoge {
hello() {
console.log('Hello');
}
}
const fuga = {
a: 'a',
b: 'b'
};
new hoge().hello();
console.log(fuga);
src/hoge.mjs
と src/fuga.mjs
の内容が混ぜ込まれて、1つになった。
続いて IIFE (Immediately Invoked Function Expression・即時実行関数式) の形式で出力してみる。
$ npx rollup src/index.mjs --format='iife'
src/index.mjs → stdout...
(function () {
'use strict';
class hoge {
hello() {
console.log('Hello');
}
}
const fuga = {
a: 'a',
b: 'b'
};
new hoge().hello();
console.log(fuga);
}());
コチラは即時関数の中にラップされていて、HTML に組み込みやすくなっている。
ファイルに出力する場合は --file
オプションを使う。
$ npx rollup src/index.mjs --format='iife' --file='dist.js'
src/index.mjs → dist.js...
created dist.js in 55ms
こんな感じ。
Rollup の設定ファイルを作る
ここまでコマンドラインで Rollup を叩いていたが、オプションなどの内容を設定ファイルに書くこともできる。
rollup.config.js
module.exports
で出力する Webpack と違い、ES Modules のexport default
を使うところが新しい
export default {
input: 'src/index.mjs',
output: {
file: 'dist.js',
format: 'iife'
}
}
で、実行時に --config
(-c
) オプションを付ければ rollup.config.js
が読み込まれる。
$ npx rollup --config
Terser を組み込む : rollup-plugin-terser
最後に、Rollup に Terser を組み込んで、コードを圧縮してみる。rollup-plugin-terser
をインストールする。terser
本体はインストールしなくて良い。
$ npm install -D rollup-plugin-terser
設定ファイルはこうする。
rollup.config.js
import { terser } from 'rollup-plugin-terser';
export default {
input: 'src/index.mjs',
output: [
// 非圧縮の通常版ファイル
{
file: 'dist.js',
format: 'cjs'
},
// Terser による圧縮版ファイル
{
file: 'dist.min.js',
format: 'cjs',
plugins: [
terser()
]
}
]
}
コレでビルドしてみる。
# package.json に npm-scripts を書いてみた
$ npm run build
> practice-rollup@ build /Users/Neo/practice-rollup
> rollup --config
src/index.mjs → dist.js, dist.min.js...
created dist.js, dist.min.js in 207ms
設定ファイルに書いたとおり、2つのファイルが生成されたことが分かる。
それぞれ中身を見てみよう。
dist.js
- Terser を組み込んでいない非圧縮版。Rollup 単体の成果
'use strict';
class hoge {
hello() {
console.log('Hello');
}
}
const fuga = {
a: 'a',
b: 'b'
};
new hoge().hello();
console.log(fuga);
dist.min.js
- Terser による圧縮が行われている。特に
fuga
変数が消えていることが顕著であろう
- Terser による圧縮が行われている。特に
"use strict";(new class{hello(){console.log("Hello")}}).hello(),console.log({a:"a",b:"b"});
こんな感じ。かなりシンプルに使えて良い感じ。