Syntax Error.

[Sy] はじめての Babel(babel-cli 使用)

2018/02/20

前回は babel-standalone というモジュールを使って Babel を使ってみましたが、この方法だとブラウザ側に負担がかかってしまうので本番サイトなどには不向きになります。今回は、 babel-cli というモジュールを使って、サーバサイドで事前にトランスパイルしておく方法で使ってみます。

前回の記事はこちら。

⇒ [Sy] はじめての Babel (CDN を使わずに babel-standalone を yarn でインストール&動作確認)

今回も、上の記事と基本的に作るページ自体は同じです。

ブラウザ側でトランスパイルするか、事前にトランスパイルした JavaScript をサーバ側から送るか、の違いになります。

1. Babel (babel-cli) をインストール

まずは作業ディレクトリを作ります。

$ mkdir hello-babel
$ cd hello-babel

続いて babel-cli をインストールします。

元々は babel という名前でモジュールが公開されていたらしいですが、大きくなりすぎたためにバージョン6 でいくつかのモジュールに分裂し、その一つが babel-cli のようです。

下記のように babel-cli をインストールすると、

$ yarn add babel-cli
・
・
success Saved 194 new dependencies.
・
・
├─ babel-cli@6.26.0
├─ babel-code-frame@6.26.0
├─ babel-core@6.26.0
├─ babel-generator@6.26.1
├─ babel-helpers@6.24.1
├─ babel-messages@6.23.0
├─ babel-polyfill@6.26.0
├─ babel-register@6.26.0
├─ babel-runtime@6.26.0
├─ babel-template@6.26.0
├─ babel-traverse@6.26.0
├─ babel-types@6.26.0
├─ babylon@6.18.0
・
・
✨  Done in 3.18s.

babel-xxx というモジュールがたくさんインストールされます。そのうち、babel-core というのが実際のトランスパイルの処理を行うモジュールになっているっぽい、と今のところ理解してます。(あまり自信ないです)

2. HTML、JavaScript を用意する

以下のファイルをそれぞれ作成しておきます。

index.html

$ vim index.html
(index.html)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>はじめてのBabel(babel-cli)</title>
</head>
<body>
  <div id="app"></div>

  <script src="/lib/app.js"></script>
</body>
</html>

src/app.js

$ vim src/app.js
(src/app.js)

const getMessage = () => "Hello Babel!";
document.getElementById('app').innerHTML = getMessage();

3. トランスパイル後のJavaScript用ディレクトリを用意する

先ほど index.html で読み込んでいた /lib/app.js というファイルは、後で Babel によって作られるトランスパイル後の JavaScript になります。

その準備として、 lib ディレクトリを作っておきます。

$ mkdir lib

4. トランスパイルしてみる

ここで一度試しに以下のコマンドで src/app.js を Babel でトランスパイルし、lib/app.js として出力してみます。

$ ./node_modules/.bin/babel src -d lib
src/app.js -> lib/app.js

libディレクトリ内にファイルが作成されているのが確認できます。

$ ls lib
app.js

中身を見てみると、

(lib/app.js)

const getMessage = () => "Hello Babel!";
document.getElementById('app').innerHTML = getMessage();

src/app.js とまったく同じコードがそのまま出力されているのがわかります。

トランスパイルしたのに変わってないんじゃ意味ないですよね?

実はここまでの状態だと Babel に設定が足りないため、さらに以下の2つを行います。

  • babel-preset-env というモジュールをインストールする
  • .babelrc という設定ファイルを作成する

5. babel-preset-env をインストールする

とりあえずインストールします。ちょっと長いですが、インストールされるすべてのモジュールを羅列します。

$ yarn add babel-preset-env
・
・
success Saved 50 new dependencies.
├─ babel-helper-builder-binary-assignment-operator-visitor@6.24.1
├─ babel-helper-call-delegate@6.24.1
├─ babel-helper-define-map@6.26.0
├─ babel-helper-explode-assignable-expression@6.24.1
├─ babel-helper-function-name@6.24.1
├─ babel-helper-get-function-arity@6.24.1
├─ babel-helper-hoist-variables@6.24.1
├─ babel-helper-optimise-call-expression@6.24.1
├─ babel-helper-regex@6.26.0
├─ babel-helper-remap-async-to-generator@6.24.1
├─ babel-helper-replace-supers@6.24.1
├─ babel-plugin-check-es2015-constants@6.22.0
├─ babel-plugin-syntax-async-functions@6.13.0
├─ babel-plugin-syntax-exponentiation-operator@6.13.0
├─ babel-plugin-syntax-trailing-function-commas@6.22.0
├─ babel-plugin-transform-async-to-generator@6.24.1
├─ babel-plugin-transform-es2015-arrow-functions@6.22.0
├─ babel-plugin-transform-es2015-block-scoped-functions@6.22.0
├─ babel-plugin-transform-es2015-block-scoping@6.26.0
├─ babel-plugin-transform-es2015-classes@6.24.1
├─ babel-plugin-transform-es2015-computed-properties@6.24.1
├─ babel-plugin-transform-es2015-destructuring@6.23.0
├─ babel-plugin-transform-es2015-duplicate-keys@6.24.1
├─ babel-plugin-transform-es2015-for-of@6.23.0
├─ babel-plugin-transform-es2015-function-name@6.24.1
├─ babel-plugin-transform-es2015-literals@6.22.0
├─ babel-plugin-transform-es2015-modules-amd@6.24.1
├─ babel-plugin-transform-es2015-modules-commonjs@6.26.0
├─ babel-plugin-transform-es2015-modules-systemjs@6.24.1
├─ babel-plugin-transform-es2015-modules-umd@6.24.1
├─ babel-plugin-transform-es2015-object-super@6.24.1
├─ babel-plugin-transform-es2015-parameters@6.24.1
├─ babel-plugin-transform-es2015-shorthand-properties@6.24.1
├─ babel-plugin-transform-es2015-spread@6.22.0
├─ babel-plugin-transform-es2015-sticky-regex@6.24.1
├─ babel-plugin-transform-es2015-template-literals@6.22.0
├─ babel-plugin-transform-es2015-typeof-symbol@6.23.0
├─ babel-plugin-transform-es2015-unicode-regex@6.24.1
├─ babel-plugin-transform-exponentiation-operator@6.24.1
├─ babel-plugin-transform-regenerator@6.26.0
├─ babel-plugin-transform-strict-mode@6.24.1
├─ babel-preset-env@1.6.1
├─ browserslist@2.11.3
├─ caniuse-lite@1.0.30000809
├─ electron-to-chromium@1.3.33
├─ regenerate@1.3.3
├─ regenerator-transform@0.10.1
├─ regexpu-core@2.0.0
├─ regjsgen@0.2.0
└─ regjsparser@0.1.5
warning No license field
✨  Done in 2.26s.

細かくは把握できてませんが、 babel-plugin-transform--xxx といった一つ一つのモジュールが、 新しい仕様で記述されたコードを古い仕様で書かれたコードにトランスパイルするためのもの というようになっているみたいです。

その plugin をまとめたものが preset と呼ばれていて、今インストールしたのは、 env という preset ということになります。

preset をインストールしたので、あとはこれを使うように設定を書くことで、うまいことトランスパイルしてくれるようになる、という仕組みです。

6. .babelrc を作成する

設定ファイルの名前は .babelrc と決められているようなので、以下のとおりファイルを作成します。

$ vim .babelrc
(.babelrc)

{
  "presets": ["env"]
}

presets の値として、 env を指定しています。これにより、先ほどインストールした preset が使われるようになります。

7. 改めてトランスパイル

ではもう一度トランスパイルしてみます。

$ ./node_modules/.bin/babel src -d lib

先ほどと同じように、 lib/app.js にトランスパイル後の JavaScript が出力されます。

中身を確認すると、

(lib/app.js)

"use strict";

var getMessage = function getMessage() {
  return "Hello Babel!";
};
document.getElementById('app').innerHTML = getMessage();

今度はちゃんと古い仕様の記述に変換されていることがわかります。