babel-plugin-external-helpers について
rollup の babel 用プラグインである rollup-plugin-babel の README に,
npm install --save-dev babel-preset-es2015 babel-plugin-external-helpers
という記載があります. babel-preset-es2015 はよく目にしますが,babel-plugin-external-helpers は初めて見たため,どういうものか調べてみました.
babel-plugin-external-helpers
babel-plugin-external-helpers は,babel での変換時に各ファイルごとに出力される共通コードを,グローバル変数を用いて1つにまとめることで,重複するコード出力を削減するプラグインです.
以下の2つのファイルを babel で変換する場合を例として,出力の違いを説明します.
src/Hoge.js
export default class Hoge { constructor(name) { this.name = name; } hello() { return `Hello ${this.name}`; } };
src/Fuga.js
export default class Fuga { constructor(name, age) { this.name = name; this.age = age; } hello() { return `Hello ${this.name} (${this.age})`; } };
例:babel でプラグインを用いずに変換した場合
babel-preset-es2015 をプリセットとして babel src -d lib
で変換すると,以下のような結果となります.
変換後のlib/Hoge.js
とlib/Fuga.js
には,var _createClass = function () { ...
や function _classCallCheck(instance, Constructor) { ...
といった class
生成に関連する共通コードが出力されています.
変換後
lib/Hoge.js
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Hoge = function () { function Hoge(name) { _classCallCheck(this, Hoge); this.name = name; } _createClass(Hoge, [{ key: "hello", value: function hello() { return "Hello " + this.name; } }]); return Hoge; }(); exports.default = Hoge; ;
lib/Fuga.js
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Fuga = function () { function Fuga(name, age) { _classCallCheck(this, Fuga); this.name = name; this.age = age; } _createClass(Fuga, [{ key: "hello", value: function hello() { return "Hello " + this.name + " (" + this.age + ")"; } }]); return Fuga; }(); exports.default = Fuga; ;
例:babel で babel-plugin-external-helpers を用いて変換した場合
babel-preset-es2015 と babel-plugin-external-helpers を用いて変換すると,以下のような出力となります.
babel-plugin-external-helpers を用いずに変換した場合と比較して,出力コードが削減されました.
これは,babelHelpers
というグローバル変数のプロパティとして,class
生成に関連するコードが定義されていることを前提とした出力となっているためです.
当然ながら,出力後の各ファイルでは babelHelpers
の定義はされていないため,このままでは動作しません.
変換後
lib/Hoge.js
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Hoge = function () { function Hoge(name) { babelHelpers.classCallCheck(this, Hoge); this.name = name; } babelHelpers.createClass(Hoge, [{ key: "hello", value: function hello() { return "Hello " + this.name; } }]); return Hoge; }(); exports.default = Hoge; ;
lib/Fuga.js
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Fuga = function () { function Fuga(name, age) { babelHelpers.classCallCheck(this, Fuga); this.name = name; this.age = age; } babelHelpers.createClass(Fuga, [{ key: "hello", value: function hello() { return "Hello " + this.name + " (" + this.age + ")"; } }]); return Fuga; }(); exports.default = Fuga; ;
babelHelpers
が定義されたコードの取得
まず,babel-cli をインストールします.
$ npm install --dev-dependencies babel-cli
babel-cli をインストールすると babel-external-helpers コマンドも導入されます.
babel-external-helpers コマンドは,babel で変換したスクリプトの利用法に合わせて,3種類の babelHelpers
の定義コードの出力が可能です.
$ $(npm/bin)/babel-external-helpers -t global # Node.jsで利用する場合 $ $(npm/bin)/babel-external-helpers -t var # ブラウザで利用する場合 $ $(npm/bin)/babel-external-helpers -t umd # UMDで利用する場合
例えば,babel で変換したスクリプトをブラウザで利用する場合は,まず babel-external-helpers コマンドで lib/util.js
を作成します.
$ $(npm/bin)/babel-external-helpers -t var > lib/util.js
次に,html から以下のように読み込みます.このとき lib/util.js
を先に読み込む必要があります.
<script src="lib/util.js"></script> <script src="lib/Hoge.js"></script>
まとめ
開発の規模によっては,babel-plugin-external-helpers を用いて,共通するコードの出力を1箇所にまとめておくと,ファイルサイズの削減が可能となります.