こんちには。
@otolabです。
Rollup.js使ってますか?
一言で言うとES6 Modules準拠のbundlerで、素直な挙動と出力の綺麗さが個人的に好きなんですが、用途としてはライブラリ作成時に強みのあると言われるものの、Webpack一強の感は否めない昨今です。
あまり情報がないと言われてしまったので、ちょっと情報を出していこうと思います。
オプション設定の詳細などは公式の情報にあたっていただくとして、今回は実際の利用例での設定サンプルを解説する形を採っています。
code
作成したコードを一部省略したもの。このコードを解説していきます。
少々長いですが、ほぼそのまま掲載します。
import babel from 'rollup-plugin-babel'
import {terser} from 'rollup-plugin-terser'
import commonjs from 'rollup-plugin-commonjs'
import nodeResolve from 'rollup-plugin-node-resolve'
import nodeBuiltins from 'rollup-plugin-node-builtins'
import nodeGlobals from 'rollup-plugin-node-globals'
import {sizeSnapshot} from "rollup-plugin-size-snapshot"
import analyze from 'rollup-plugin-analyzer'
import visualizer from 'rollup-plugin-visualizer'
import replace from 'rollup-plugin-replace'
import importAlias from 'rollup-plugin-import-alias'
import vue from 'rollup-plugin-vue'
import fs from 'fs'
const settings = ({name, format}) => {
return {
input: `src/index.${name}.js`,
output: [
{
file: `dest/build.${name}.js`,
format,
name: `__${name}`,
sourcemap: true,
}
],
plugins: [
vue({
include: ['**/*.vue', '/**/*.vue']
}),
commonjs({
extensions: [ '.js', '.vue' ],
}),
nodeGlobals({
buffer: false // falseにできると容量を削れる
}),
nodeBuiltins(),
nodeResolve(),
importAlias({
Paths: {
"lodash-custom": `${__dirname}/src/verdors/lodash.custom.js`, // esm版使おうという話はありつつも
"libs": `${__dirname}/src/libs`,
},
Extensions: ['js', 'vue']
}),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
babel({
exclude: 'node_modules/**',
runtimeHelpers: true,
babelrc: false,
presets: [
[
'@babel/env',
{
modules: false,
"targets": {
"ie": 11,
}
}
]
],
"plugins": [
// 必要があればいろいろ
]
}),
analyze({
writeTo: (analysisString) => fs.writeFileSync(`dest/analysis.${name}.txt`, analysisString)
}),
sizeSnapshot(),
visualizer({
filename: `dest/stats.${name}.html`
}),
terser()
],
}
}
export default [
settings({name: 'core', format: 'iife'}),
settings({name: 'plugin', format: 'cjs'}),
]
rollup.config.js
rollupの設定を行うファイルで、jsファイルになっています。export defaultしたオブジェクトが実行時の設定になる仕組み。
(ちょっと特殊な例ですが)複数の設定を配列で返すことができるので、エントリファイルごとに設定を組んで一度に処理することができます。共通の設定部分を切り出して、プログラムしつつ設定を書くことが出来て便利。
JavaScript APIもあるので、複雑なことをやりたい場合はそちらを。
input / output
input
entryとなるファイル名を書いておくだけです。
複数のエントリ指定からの共通部分のchunk切り出しなどもできますが、あまり使ったことがないので割愛します。
output
出力フォーマット別などで、複数の出力先を指定することが出来ます。
フォーマットはesm
, cjs
, iife
がよく使うところで、「ライブラリ作成に強い」のはこの辺りに起因します。
なお、iifeはname
が必須で、この名前のグローバル変数にentryファイルのexport defaultが代入されます。
plugins
プラグインの一覧としてまとまっているので、基本的にはここから探します。
babel
ご存知babelです。
個人的には.babelrc
を使わず設定ファイル内に閉じるのが好きですが、その辺は調整できます。
イマドキはbabel/envを使うのが推奨されているので、サポート対象に合わせて調整しましょう。
commonjs
cjs(commonjs)形式のモジュールをimport可能にし、またその中でrequire()
を使えるようにします。小さな変換用の仮ファイルを追加することで扱えるように変換しているようです。
オプションについてですが、.vue
を使いたいときはextensionsに.vue
を含めましょう。extensionsに含まれない拡張子のファイルにはcommonjs => ES6化の処理が掛かりません。
node-resolve, node-builtins, node-globals
resolveがnode_modules
の検索を、builtinsがNode特有の機能のpolyfillを、globalsがprocess
などのグローバル変数を再現します。
基本的にcommonjsを含めてたこの4つはセットで使うことが多いと思います。
それぞれオプションを意識することは少ないですが、ファイルサイズにシビアな場合には、globalsのbuffer: false
などを検討する価値があるかもしれません。
terser
minifyします。
uglifyよりES6に対応しているterserを使うほうが便利じゃないかと思います。機能はほぼほぼ同じ。
普通の用途だと特にオプションを使うことはない気がしますが、細かく設定もできるようです。
visualizer, size-snapshot, analyze
ファイルサイズや依存関係をうまく表現してくれるプラグイン。
visualizerは特に、グラフィカルな表示をするhtmlを出してくれるのでおすすめです。browserifyのdiscというツールを使っていたのですが、それと同じ表現をしてくれるのがなかなかにくい。表現方法は選択できるようです。
sizeSnapshotはサイズ計算特化で、minifyした場合やgzした場合のサイズなどをシンプルに表示してくれるので便利。
analyzeはファイルの依存関係などをファイルに書き出してくれます。自分で処理したい場合向け?
いずれも書き出し先指定などを持っているので、環境に合わせて設定しましょう。
vue
.vue
でお馴染みのVue.jsのSFC(単一ファイルコンポーネント)をimport可能にします。
内部ではvueifyやwebpackのvue-loaderなどと同じ(たぶん)vue-template-compiler
が使われているので使用感も同じです。
vueのモジュールとバージョン合わせが必要になるので(最近のは違う?)その辺りは注意です。
replace
最終的に出力する内容にたいしてreplaceをかけてくれます。原始的ですが強い。
おもな用途としてはprocess.env.NODE_ENV
の置換です。node-globalsで対応してくれよと思わなくもないんですが、node-globalsもcore-jsのprocess実装に依存している(?)らしく、そのへんは現状対応してくれていないみたいです。
import-alias
aliasを設定します。import a from 'libs/a'
やimport _ from 'lodash-custom'
などの名前でポロッとファイルを置いたケースなどで使います。
変換先は${__dirname}/path/file
で統一したほうが良いのかな?というのが最近得た知見です。commonjsと併用したとき、どうも多重にバンドルされるケースがあるようなのです。(この辺は要調査)
まとめ?
rollup.jsはシンプルなバンドルツールです。ほとんど全ての機能はプラグインとして提供されており、要・不要にあわせて自分で組み合わせていくスタイルになっています。
というわけで、実例のコードと、よく使うプラグインの解説をしてみました。
出力もきれいなのでちょっと実験してみると面白いですよ。