この記事は「ECMAScript2015/ES6特集」の第3回目です。この特集ではJavaScriptの次世代仕様であるECMAScript 2015(ECMAScript 6)を取り上げ、歴史や経緯から追加された機能や文法の詳細など、複数回に渡って解説していきます。
ここではECMAScriptの新仕様を先取りできるトランスパイラ、Babelの紹介を行います。
Babelとは
Babelとは、2014/9から開発が始まっているECMAScriptコンパイラです。
機能としては、ECMAScript2015 (ES6)やECMAScript7などで書かれたソースコードを一般的なブラウザがサポートしているECMAScript5の形式に出力することができます。
1 2 3 4 5 6 7 |
const obj = (() => { return { method() { alert('Hello Babel!'); } }; })(); |
1 2 3 4 5 6 7 8 9 |
'use strict'; var obj = (function () { return { method: function method() { alert('Hello Babel!'); } }; })(); |
Babelは最低限の機能をIE8以降で、フル機能をIE10以降でサポートします。
(実際にはIE9以降から使用することを推奨します)
当初Babelは6to5と呼ばれていましたが、ECMAScript7の仕様なども取り込むようになったため、バージョンを想定しないBabelという名前に変更されました。
Babelの特徴
Babelと同じように「トランスパイルすることでJavaScriptのコードを出力する」ツールにはTypeScriptやCoffeeScriptなどがあります。
それらと比較するとBabelは「ECMAScript標準仕様をベースにしている(*)」という特徴があります。
(*) 実際にはJSXもサポートしているため、必ずしもECMAScript標準仕様のみをサポートしているわけではありません。
このため、「いずれ標準実装される仕様を先取りできる」、「Babel自体が廃れても同じような標準仕様を扱うツールがあれば乗り換えできる」といった利点があります。
簡単に始める方法
それでは早速Babelを使ってみましょう。
お手軽に始める場合、Babelの公式サイトで公開されているオンライン上のトランスパイルサービスが便利でしょう。
これは左側にコードを書くとトランスパイルした結果を右側に出力してくれます。
もちろんこのまま開発を行うのは難しいため、実際には手元にツールをインストールして使うことになります。
Babelのインストール
Babelはnpm経由で以下のようにインストールします。
$ npm install --global babel
これでbabel
コマンドが使用できるようになりました。
CLIを使った変換方法
それではまずはbabel
コマンド経由で変換してみましょう。
babel
コマンドでは以下のようにファイル名を引数に与えるか、標準入力にソースを渡すことによって標準出力へ変換結果を出力します。
$ cat sample.js
() => {}
$ babel sample.js
"use strict";
(function () {});
$
この方法でも変換はできますが、実際の現場では次で紹介するような別のコマンド経由で変換されることが一般的です。
gulpを使った変換方法
では次にgulpを使った変換方法を紹介します。
gulpを使って変換するためには、gulpとBabelを繋げるためのgulp-babelというパッケージをインストールします。
$ npm install --global gulp
$ npm install --save-dev gulp-babel
それでは変換してみましょう。
まずgulpfile.js
に以下のように記述します。
1 2 3 4 5 6 7 8 |
var gulp = require('gulp'); var babel = require('gulp-babel'); gulp.task('default', function () { return gulp.src(['src/*.js', 'src/**/*.js']) .pipe(babel()) .pipe(gulp.dest('dist')); }); |
この状態でgulp
コマンドを実行することで、src/
以下のjsファイルをBabelで変換してdist
以下に書き出すことができます。
gruntを使った変換方法
次はgruntを使った変換方法を紹介します。
gruntを使って変換するためには、gulpの場合と同様にgrunt-babelというパッケージをインストールします。
$ npm install --global grunt-cli
$ npm install --save-dev grunt grunt-babel
それでは変換してみましょう。
Gruntfile.js
に以下のように記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
module.exports = function(grunt) { grunt.initConfig({ babel: { dist: { files: [{ "expand": true, "cwd": "src/", "src": ["*.js", "**/*.js"], "dest": "dist/", "ext": ".js" }] } } }); grunt.loadNpmTasks('grunt-babel'); grunt.registerTask('default', ['babel']); }; |
この状態でgrunt
コマンドを実行することで、src/
以下のjsファイルをBabelで変換してdist/
以下に書き出すことができます。
Browserifyを使った変換方法
ここまではタスクランナー経由での使い方を紹介しましたが、最後にBrowserify経由での変換方法もご紹介します。
Browserifyとは、以下のようにNode.jsで使える外部ライブラリを読み込むrequire構文(CommonJS)をブラウザ上でも使えるように変換するためのツールです。自動的に外部ライブラリの参照先のファイルを結合してひとつのファイルにまとめてくれます。
1 2 3 |
module.exports = function () { console.log('Hello browserify!'); }; |
1 2 |
var exportsCode = require('./exports.js'); exportsCode(); // console.log('Hello browserify!'); |
Babelは、同じように外部ライブラリを読み込むECMAScritpt2015 (ES6)のmodule構文を上記のようなrequire構文)に変換してくれますが、ひとつのファイルにまとめてくれる機能はありません。そのため、実際の実行ではエラーになってしまいます。
1 2 3 |
export default function () { console.log('Hello ES2015 exports!'); }; |
1 2 |
import exportsCode from './exports.js'; exportsCode(); // console.log('Hello ES2015 exports!'); |
これを解決するには、Babelだけでなく、Browserifyを組み合わせてrequire構文をブラウザでも実行できるようにする必要があります。これらを組み合わせた場合、ES2015のmodule構文で書いたものが、Babelによってrequire構文に変換され、require構文の(ブラウザでの)実行に必要なファイルの結合処理をBrowserifyが行う形となります。
このようにWebフロントエンドの開発の場合、BrowserifyとBabelはセットで使われることが多いです。
BrowserifyとBabelの連携方法は、単純にBabelの出力結果をBrowserifyに渡すだけでなく、Browserifyのもつプラグイン機構でBabelを呼び出すこともできます。
では、Browserify経由でBabelを実行するためのbabelifyというパッケージをインストールします。
$ npm install --global browserify
$ npm install --save-dev babelify
Browserifyはgruntやgulp経由で起動する方法もありますが、以下のようにコマンドラインからでも起動できます。
$ browserify src/app.js -t babelify -o dist/app.js
-t
でbabelifyを指定することで変換時にBabelを呼び出しています。
ここまで変換方法を紹介してきましたが、これ以外にも様々な方法でコードを変換することができます。
他のツールとの親和性はBabelの大きな特徴で、さまざまなツールを使用している状態でもスムーズに導入することができます。
オプション
ここまで紹介してきた内容でも最低限Babelでの変換は行えますが、細かい挙動を制御する場合オプションの指定が必要になる場合があります。
Babelにはさまざまなオプションがありますが、ここではその中から主要なものを取り上げて紹介します。
- stage
BabelはECMAScript2015 (ES6), ECMAScript7をECMAScript5に変換しますが、ECMAScript2015 (ES6), ECMAScript7の仕様でもまだ議論中のものもあり、安定度はまちまちです。
そこで、ECMAScriptの中でもまだ議論しきれていない仕様に関しては、stageという概念を使って安定度を示しています。
Babelはこのstageを指定する機能を備えており、stageを指定することでまだ議論の進んでいない仕様も使うことができます。
各stageでどういった機能が使えるようになるかは、こちらをご覧ください。
初期値は2が指定されており、草案(Draft)レベルのものが使用できます。
基本的には初期値で構いませんが、どうしても先取りしたい仕様がある場合には仕様が変わってしまうリスクを踏まえた上で、より新しい仕様を使うこともできます。
- sourceMaps
JavaScriptのコンパイラは性質上、元のソースコードと違った形式で出力されるため、実行時に何か問題があった場合にデバッグが困難になるという性質があります。
この問題に関しては標準仕様としてSourceMapという仕様が存在し、モダンブラウザではこの機能をサポートしています。
SourceMapを使うことで変換前のコードと変換後のコードを対応付けることができるため、実行時に問題が発生しても元のソース上でどこに問題があったのかを容易に把握することができます。
BabelのsourceMapsオプションはソースコードと同時にsourceMapファイルを出力することができ、trueを指定した場合変換後のソースとは別にsourceMapファイルを、”inline”を指定した場合変換後のソースファイルにsourceMapファイルを埋め込んで出力できます。
オプションの指定方法
さまざまなツールと連携できる点が魅力のBabelですが、連携する場合に問題になるのがBabel自体に対するオプションの指定方法です。
連携するツールによってはBabelに対してのオプションを指定する方法を提供している場合もありますが、場合によってはドキュメントに書かれていなかったり提供されていないこともあります。
そこで便利なのが設定を独立して記述できる.babelrcファイルです。
このファイルをBabelを実行するフォルダ(基本的にpackage.jsonと同じ場所)へ設置することで、連携ツール毎のオプション指定の方法を気にすることなく一括でオプションを指定することができます。
$ cat .babelrc
{
"stage": 1
}
最後に
駆け足でしたがここまでBabelの紹介をしてきました。
Babelを使った開発はすでに一般的に行われており、公開されている製品での使用もよく見るものになっています。
皆様もこれまでブラウザがサポートしなければ使えなかったECMAScriptの最新仕様を、自由に使える環境での開発を是非体験してみてください。