Babel + rollup.js で ES3環境向けトランスパイル
Babel + rollup.js で ES3環境向けトランスパイル:
moduleのimportを使用したjavascriptを、Babelとrollup.jsを利用して、es3相当にトランスパイルします。
本記事で前提とする環境は以下の通りです。
バージョンが異なる場合は本ドキュメントの内容が適用できなくなる場合がありますのでご注意ください。
es3はブラウザ上からはすっかり消滅しましたが、アプリケーションに組み込まれた独自のjavascriptエンジンではまだ存在します。
私の場合、Adobe CCアプリのバッチ処理のためjsを使用しています。このjsエンジンが非常に古いため、es3相当のコードしか実行できません。
importを利用できれば、共通処理をくくり出せるため、バッチの生産性が高くなります。
どうにかしてimportを使用できる状況でコードを書き、Adobe CC上で実行できるようにトランスパイルします。
以前は同様の目的のため、モジュールバンドラーにwebpackを利用していました。
webpackは高機能な反面、バンドル先のファイルに独自の関数を追加します。これはwebpack自身の機能を実現するためです。
この独自の追加部分がES5を想定して作成されているため、バンドル元ファイルによってはES3環境での動作を妨げます。
そこでモジュールバンドラーにrollup.jsを利用することにしました。
こちらはjsファイルのバンドルに特化したモジュールバンドラーになります。rollup.jsのプラグインを追加しない状態では、独自の関数をバンドル先に埋め込むことがありません。
rollup.jsの概要と利点については、こちらの記事でより詳しく解説されています。
Rollupがちょうどいい感じ
上記のpackage.jsonに指定されているモジュールをインストールしてください。
すべてnpmからインストールが可能です。
babelの設定は以下の通りです。
"@babel/preset-env", { "loose" : true }でLoose modeを有効にすると、Object.definePropertiesを使用しないようにトランスパイルが行われます。また、{ "modules": false } を指定することで、importしたモジュールが単一のファイルにまとめられます。
babelの設定についてはこちらの記事を参考とさせていただきました。ありがとうございます。
MSを偲び、ここにIE6対応SPAの作り方を記す
プラグインはそれぞれ対応した構文のトランスパイルを行います。
その他のes2015以降の機能を利用したい場合は、対応するbabel-pluginを追加してください。
例として、Object.assignを使用したい場合は@babel/plugin-transform-object-assignを追加します。
次にrollup.jsを利用してimportしたファイルをバンドルします。
今回はrollup.jsをCLIではなくAPIから利用しています。
これはrollupのinputファイルをnode-globを利用して複数指定するためです。
rollup.jsの複数input指定を行うプラグインとしてはrollup-plugin-multi-inputなどがありますが、このプラグインでは出力ファイルに共通のimportがある場合、その部分をチャンクとしてくくり出してしまいます。
AdobeCCのバッチでは動的なimportが行えないため、node.jsからrollup.jsを利用しています。
最後に
目標
moduleのimportを使用したjavascriptを、Babelとrollup.jsを利用して、es3相当にトランスパイルします。
前提とする環境
本記事で前提とする環境は以下の通りです。バージョンが異なる場合は本ドキュメントの内容が適用できなくなる場合がありますのでご注意ください。
package.json
{ "devDependencies": { "@babel/cli": "^7.2.3", "@babel/core": "^7.2.2", "@babel/plugin-transform-member-expression-literals": "^7.2.0", "@babel/plugin-transform-property-literals": "^7.2.0", "@babel/plugin-transform-property-mutators": "^7.2.0", "@babel/plugin-transform-reserved-words": "^7.2.0", "@babel/preset-env": "^7.2.3", "glob": "^7.1.3", "rollup": "^0.68.2", "rollup-plugin-babel": "^4.1.0" } }
なぜそんな古い規格を?
es3はブラウザ上からはすっかり消滅しましたが、アプリケーションに組み込まれた独自のjavascriptエンジンではまだ存在します。私の場合、Adobe CCアプリのバッチ処理のためjsを使用しています。このjsエンジンが非常に古いため、es3相当のコードしか実行できません。
importを利用できれば、共通処理をくくり出せるため、バッチの生産性が高くなります。
どうにかしてimportを使用できる状況でコードを書き、Adobe CC上で実行できるようにトランスパイルします。
なぜrollup.js?
以前は同様の目的のため、モジュールバンドラーにwebpackを利用していました。webpackは高機能な反面、バンドル先のファイルに独自の関数を追加します。これはwebpack自身の機能を実現するためです。
この独自の追加部分がES5を想定して作成されているため、バンドル元ファイルによってはES3環境での動作を妨げます。
そこでモジュールバンドラーにrollup.jsを利用することにしました。
こちらはjsファイルのバンドルに特化したモジュールバンドラーになります。rollup.jsのプラグインを追加しない状態では、独自の関数をバンドル先に埋め込むことがありません。
rollup.jsの概要と利点については、こちらの記事でより詳しく解説されています。
Rollupがちょうどいい感じ
インストール
上記のpackage.jsonに指定されているモジュールをインストールしてください。すべてnpmからインストールが可能です。
babelの設定
babelの設定は以下の通りです。"@babel/preset-env", { "loose" : true }でLoose modeを有効にすると、Object.definePropertiesを使用しないようにトランスパイルが行われます。また、{ "modules": false } を指定することで、importしたモジュールが単一のファイルにまとめられます。
babelの設定についてはこちらの記事を参考とさせていただきました。ありがとうございます。
MSを偲び、ここにIE6対応SPAの作り方を記す
{ "presets": [ [ "@babel/preset-env", { "loose": true, "modules": false } ] ], "plugins": [ "@babel/transform-member-expression-literals", "@babel/transform-property-literals", "@babel/plugin-transform-property-mutators", "@babel/plugin-transform-reserved-words" ] }
その他のes2015以降の機能を利用したい場合は、対応するbabel-pluginを追加してください。
例として、Object.assignを使用したい場合は@babel/plugin-transform-object-assignを追加します。
rollup.jsの実行
次にrollup.jsを利用してimportしたファイルをバンドルします。今回はrollup.jsをCLIではなくAPIから利用しています。
これはrollupのinputファイルをnode-globを利用して複数指定するためです。
bundle.js
const path = require("path"); const rollup = require("rollup"); const babel = require("rollup-plugin-babel"); const glob = require("glob"); const path = require("path"); const srcDir = "./src"; const distDir = "./bin"; // ./src以下のjsファイルのリストを取得する。ただし_から始まるファイルとmodulesディレクトリは除外する。 const entries = glob.sync("**/*.js", { ignore: ["modules/**/*.js", "**/_*.js"], cwd: srcDir }); //リストアップしたjsファイルをバンドルする。 for (let entry of entries) { const inputOptions = { input: path.resolve(srcDir, entry), plugins: [babel()] }; const outputOptions = { format: "cjs", file: path.resolve(distDir, entry) }; build(inputOptions, outputOptions); } async function build(inputOptions, outputOptions) { const bundle = await rollup.rollup(inputOptions); await bundle.write(outputOptions); }
AdobeCCのバッチでは動的なimportが行えないため、node.jsからrollup.jsを利用しています。
package.json
"scripts": { "bundle": "node bundle.js" }
bundle.js
を実行すればbin
ディレクトリにバンドルされたjsファイルが出力されます。
コメント
コメントを投稿