ECMAScript® 2015とBabelを使う

2015年6月にECMAScript® 2015の仕様が策定されました。 しかしブラウザーで使う場合は、まだ実装されていないものもあるようです。 そのためBabelでECMAScript 5に変換してから使うのが主流のようですが、変換する方法がいくつもあって、結局どれが良いのかわからなかったので調べてみました。

環境

  • OS X El Capitan バージョン 10.11.3
  • Node.js バージョン 5.4.1
  • gulp バージョン 3.9.0
  • gulp-babel バージョン 6.1.1
  • babel-preset-es2015 バージョン 6.3.13

ECMAScript® 2015?

Standard ECMA-262

6th Edition / June 2015

ECMAScript® 2015 Language Specification

This is the HTML rendering of ECMA-262 6th Edition, The ECMAScript 2015 Language Specification.

ECMAScript 2015 Language Specification – ECMA-262 6th Edition

興味深い記事です。

Babel?

Babel is a JavaScript compiler.

Babel · The compiler for writing next generation JavaScript

ツール

How to use Babel with your tool of choice

  1. Choose your tool

Using Babel · Babel

ツールの種類を見てみます。

  • Babel built-ins
    • CLI
    • Require hook
  • Build systems
    • Broccoli
    • Browserify
    • Brunch
    • Duo
    • Gobble
    • Grunt
    • Gulp
    • jspm
    • Make
    • MSBuild
    • RequireJS
    • Rollup
    • Sprockets
    • Webpack
    • Fly
  • Frameworks
    • Ember
    • Meteor
    • Rails
    • Sails
  • Test frameworks
    • Jasmine
    • Jest
    • Karma
    • Mocha
  • Utilities
    • Connect
    • Nodemon
  • Language APIs
    • C# / .NET
    • Node
    • Ruby
  • Template engines
    • Jade
  • Editors and IDEs
    • WebStorm
  • Debuggers
    • Node Inspector

たくさんのツールがあります。

変換する方法を検索した時に、Gulpを使った方法とBrowserifyを使った方法が記載されていたり、Gulpを使った方法とWebpackを使った方法が記載されていたりして混乱しました。 複数のツールを組み合わせて成り立っているので、その相互の関連がわからなかったんです。 でもBrowserifyもWebpackもGulpのプラグインがあるんだから全部Gulpのビルドシステムから使えばいいと考えたらシンプルになりました。 結局、Gulpで結合(concat)したり、圧縮(uglify=醜くするという意味なんですね)したり、CSSのコンパイル(sass)したりしているんだからBabelを使うところだけコマンドでbrowserify ...としたり、webpack ...としたりするのは違和感があったんです。 gulpからプラグインを経由せずにbrowserifywebpackをするのも違和感があります。

なので、GulpのプラグインからBabelを使う方法を書いていきます。

GulpのプラグインからBabelを使う

プロジェクトディレクトリーの作成

プロジェクトを最初から作ることとして、ターミナルからプロジェクトのディレクトリーを作成します。 [project-name]は任意のディレクトリーの名前に変えます。

$ mkdir [project-name]
$ cd [project-name]

package.jsonファイルの作成

GulpやBabelのパッケージを管理するためpackage.jsonファイルを作成します。

$ npm init -y

パッケージのインストール

GulpとそのプラグインのBabelをインストールします。 Gulpは実行の仕組み上、グローバルとローカルに必要なので--global--save-devの両方のオプションでインストールします。 Babelは開発時だけ使うツールなので--save-devオプションを指定してインストールします。 --saveオプションは開発時じゃなくて実行時に使うものをインストールする時に使います。

$ npm install --global gulp
$ npm install --save-dev gulp
$ npm install --save-dev gulp-babel
$ npm install --save-dev babel-preset-es2015

gulpfile.jsファイルの作成

gulpfile.jsファイルを以下の内容で作成します。

var gulp = require("gulp");
var babel = require("gulp-babel");

gulp.task("default", function () {
  return gulp.src("src/app.js")
    .pipe(babel())
    .pipe(gulp.dest("dist"));
});

.babelrcファイルの作成

.babelrcファイルを作成します。 ES2015 preset · BabelOptions · Babelを参考にBabelのオプションのファイルを作成します。 ここでは最低限の設定として以下のファイルを作成しました。

{
  "presets": ["es2015"]
}

実行ファイルの作成

確認のためのsrc/app.jsファイルを作成します。

const evens = [0, 2, 4, 6, 8, 10];
const fives = [];

// Expression bodies
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);

// Statement bodies
nums.forEach(v => {
  if (v % 5 === 0)
    fives.push(v);
});

// Lexical this
var bob = {
  _name: "Bob",
  _friends: [],
  printFriends() {
    this._friends.forEach(f =>
      console.log(this._name + " knows " + f));
  }
};

console.log(`odds: ${odds}`);
console.log(`nums: ${nums}`);
console.log(`fives: ${fives}`);

bob._friends = ['friends1', 'friends2', 'friends3'];
bob.printFriends();

ファイルの確認

ここまでで以下のようなディレクトリー構成になっています。

.
├── .babelrc
├── gulpfile.js
├── package.json
└── src
    └── app.js

変換

変換してみます。

$ gulp

dist/app.jsファイルが作成されます。

..
├── .babelrc
├── dist
│   └── app.js
├── gulpfile.js
├── package.json
└── src
    └── app.js

実行

実行してみます。

$ node dist/app.js
odds: 1,3,5,7,9,11
nums: 0,3,6,9,12,15
fives: 0,15
Bob knows friends1
Bob knows friends2
Bob knows friends3

Node.jsで実行してしまってるので、ちゃんとした確認は各ブラウザーでした方がいいのかもしれないですけど、それでも実行できました。

終わり

今までもBabelを使っていましたけど、パッケージのソースをGitHubで見たりすると、たくさんのツールが使われていて、それぞれのツールの境界が複雑に見えてしまっていました。 今回、調べてみたことで少し関連が理解できましたので、良い機会になりました。

参考