【a-blog cms】developテーマから理解するBabel
目次
今回は a-blog cms の developテーマの Babel 設定ファイルである .babelrc
が何をしているかを記事にしていきます。この記事を最後まで読むことで Babel についての基礎的なことが理解できます。developテーマとは a-blog cms が提供しているテーマの1つです。a-blog cms でWebサイトを開発する際のテンプレートとフロントエンドに関する開発環境を整えています。本記事はフロントエンドの開発環境の1つである。 Babel に焦点を絞って書いていきます。
developテーマとは
先程、developテーマとはフロントエンドの開発環境が整ったテーマだと説明しましたが、具体的にどのような機能があるのか簡単に説明します。 大きく以下のような機能が備えられています。
機能 | 概要 |
---|---|
SCSSのコンパイル | SCSSをCSSにコンパイルします。 |
JSファイルの結合 | 複数のJSファイルを1つのファイルに結合します。 |
コードのLintチェック | ESLintやstylelintを使用して、JSやSCSSおよびCSSのコードをチェックします。 |
Live Reload | ファイルの変更があった場合に、ブラウザを自動的にリロードします。 |
ソースコードの整形 | EditorConfigを使い、ソースコードを整形します。 |
SVGアイコンの使用 | Font Awesome 5 のSVG with JavaScriptを利用して、SVGアイコンを表示します。 |
Babel の設定ファイル
Babel とはJavaScriptコンパイラです。古いブラウザまたは環境でECMAScript2015 +コードを下位互換性のあるバージョンのJavaScriptに変換するために使用されます。早速 developテーマの Babel 設定ファイルを見てみましょう。
{
"presets": [
["@babel/preset-env",
{
"targets": {
"ie": 11
},
"useBuiltIns": "usage",
"corejs": 3
}
],
["@babel/preset-react"],
["@babel/preset-typescript"]
],
"plugins": [
"transform-es3-property-literals",
"transform-es3-member-expression-literals",
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
["@babel/plugin-transform-modules-commonjs", { "strictMode": false }]
],
"env": {
"production": {
"plugins": [
"babel-plugin-minify-dead-code-elimination"
]
}
}
}
このBabel の設定ファイルを見てみると、大きく分けて presets
, plugin
, env
の3つに分けられます。それぞれ詳しく見ていきたいと思います。
プリセット
プリセットとは、Babel プラグインのセットのことです。そもそも Babel の本体である @babel/core
は JavaScript からコードを入力・解析し、ASTに変換します。その後、何らかの変換処理を行い、 AST から再度 JavaScript コードに変換・出力します。この何らかの変換処理を行うのがプラグインです。
つまり、 Babel はプラグインなしではなんのトランスパイルも行われないということです。開発者は*何らかの変換処理**を行うためのプラグインを適切に選択する必要があり、とても面倒なのです。 そんな面倒くささを解決するためのものがプリセットです。プリセットとはいくつかのプラグインのセットです。プリセットは対応ブウラウザなどの大雑把な情報を元に、必要なプラグインを自動で選択してくれるため適切なプラグインを選択する面倒さから開放されます。
developテーマにデフォルトで設定されているプリセットは @babel/preset-env
, @babel/preset-react
, @babel/preset-typescript
の3種類になります。それぞれ詳しく説明していきます。
@babel/preset-env
は、指定した任意のターゲット環境を受け取り、数あるプラグインの中から必要なプラグインを自動で選択して、最新の JavaScript を動くようにしてくれます。 @babel/preset-env
にはオプションを指定することができます。 developテーマの .babelrc
ファイルで見ると下記の部分になります。
["@babel/preset-env",
{
"targets": {
"ie": 11
},
"useBuiltIns": "usage",
"corejs": 3
}
],
targets
オプションにはサポートしたいブラウザ名を key
にバージョンを value
に記述します。記述することでサポートしたいブラウザの最小バージョンを指定することができます。
次に出てくるオプションが useBuiltIns
です。このオプションを何を設定しているかというと、 @babel/preset-env
でどのようにPolyfillを扱うかを指定しています。設定できる値は3種類で "usage"
| "entry"
| "false"
です。
それぞれの効果を以下の表にまとめました。
値 | 概要 |
---|---|
"usage" | 必要な Polyfill のみ適用する |
"entry" | `core-js` の import 文をターゲットブラウザが必要とするモジュールに置き換える |
"false" | Polyfill しない(デフォルト) |
develop テーマでは "usage"
を指定しているため、必要な Polyfill のみ適用しています。バンドラーが同じ Polyfill を1回だけ読み込むため、パフォーマンスの視点からみてメリットがあります。
デメリットとしては、必要な Polyfill の選定はあくまで機械的に行われるため、トリッキーな場合は適用されない場合があります。
最後の @babel/preset-env
のオプションである core-js
は Polyfill を含んだライブラリである core-js
のバージョンを指定します。
残り2つのプリセットである @babel/preset-react
と @babel/preset-typescript
は React と TypeScript のソースコードをコンパイルするためのプリセットです。
プラグイン
develop テーマの Babel プラグイン設定ファイルは下記になります。
"plugins": [
"transform-es3-property-literals",
"transform-es3-member-expression-literals",
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
["@babel/plugin-transform-modules-commonjs", { "strictMode": false }]
],
transform-es3-property-literals
は予約されているプロパティの key
をリテラルに変換します。
サンプルコードは↓です。
In
var foo = {
catch: function () {}
};
Out
var foo = {
"catch": function () {}
};
2つ目に、 transform-es3-member-expression-literals
は予約後のプロパティをブラケット記法に変換します。
サンプルコードは↓です。
In
foo.const;
Out
foo["const"]
3つ目のプラグインである @babel/plugin-transform-runtime
は、Babelの挿入されたヘルパーコードを再利用してコードサイズを節約することができるプラグインです。
4つ目のプラグインである @babel/plugin-syntax-dynamic-import
は dynamic import を使用できるようにするプラグインです。
5つ目のプラグインである @babel/plugin-proposal-class-properties
はクラスを使用できるようにするプラグインです。
6つ目のプラグインである @babel/plugin-proposal-object-rest-spread
はスプレッド構文とレスト構文を使用できるようにするプラグインです。
サンプルコードは↓です。
In
const a = { a: "foo", b: "bar" };
const b = { ...a, c: "hoge" };
Out
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const a = {
a: "foo",
b: "bar"
};
const b = _objectSpread(_objectSpread({}, a), {}, {
c: "hoge"
});
最後のプラグインである @babel/plugin-transform-modules-commonjs
は ESmodule を CommonJS 形式に変換します。
サンプルコードは↓です。
In
export default 42;
Out
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _default = 42;
exports.default = _default;
ENV
最後に env
オプションの中身を見ていきます。
env
オプションは、 { [envKey: string]: Options }
のように記述できます。効果としては envKey
の値に envName
(つまり、 production
や development
など)を記述することで、記述した環境内のみで適応するオプションを設定することが出来ます。
developテーマでは、下記の通りの記述がされており、本番用のコンパイル時のみ、 babel-plugin-minify-dead-code-elimination
が適用される設定になっています。
"env": {
"production": {
"plugins": [
"babel-plugin-minify-dead-code-elimination"
]
}
}
このように env
オプションを設定することで、開発時と本番時などの環境の違いによってBabelの設定を分けることが出来ます。
また、本番時のみ適用された babel-plugin-minify-dead-code-elimination
はコンパイル時に使用されていないコードを削除して minify してくれるプラグインです。
サンプルコードは↓です。
In
function foo() {var x = 1;}
function bar() { var x = f(); }
function baz() {
var x = 1;
console.log(x);
function unused() {
return 5;
}
}
Out
function foo() {}
function bar() { f(); }
function baz() {
console.log(1);
}
まとめ
今回は developテーマの .babelrc
を題材に、Babel についての記事を書きました。こういったツールなどはなんとなくでも動いてくれて、中で何をしているのかがわからなくても使用できます。しかし、中身で何をしているのかを知るとさらに理解が深まり、できることも増えるのではないかと感じました。また、フロントエンドのツールにはもう1つ Webpack というものがありますが、そちらについても次回以降、同じように develop テーマの設定ファイルを題材に読み解いていきたいと思います。