【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 (つまり、 productiondevelopment など)を記述することで、記述した環境内のみで適応するオプションを設定することが出来ます。

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 テーマの設定ファイルを題材に読み解いていきたいと思います。


関連記事

この記事のハッシュタグに関連する記事が見つかりませんでした。

最新記事

カテゴリー

アーカイブ

ハッシュタグ