前々からちょっと気になっていた、Babelをちょっと試してみることにしました。
Babelって何?という話ですが、ECMAScript 6(ECMAScript 2015)で書かれたコードを、ECMAScript 5または3の機能だけを使ったコードに変換するものらしいです。
「トランスパイラ」というそうな。
で、今回このBabelを試してみます。
ECMAScript 2015の機能については、Babelのドキュメントと、WEB+DB PRESSを見ながら少し試してみました。
- 作者: 佐藤鉄平,小林明大,石村真吾,坂上卓史,上原誠,鳥居英,佐藤歩,泉水翔吾,うさみけんた,伊藤直也,高橋侑久,佐藤太一,hayajo,橋本翔,西尾泰和,中島聡,はまちや2,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2015/06/24
- メディア: 大型本
- この商品を含むブログ (2件) を見る
その他、参考にしたのはこちら。
Babelで始める!モダンJavaScript開発 | HTML5Experts.jp
Babelを使って次期JavaScript、ES6を体験しよう - アシアルブログ
How to get sourcemaps for gulp+babel+browserify+uglify - Stack Overflow
今回は、CLIでの実行と、gulp+Browserifyで試してみたいと思います。
CLI
まずは、コマンドラインでBabelを試してみます。
ドキュメントは、こちら。
インストール。
$ npm install --global babel-cli
なのですが、ドキュメントを見るとグローバルインストールするのは「bad idea」らしいです。
Note: Since it's generally a bad idea to run Babel globally you may want to uninstall the global copy by running npm uninstall --global babel-cli.
https://babeljs.io/docs/usage/cli/
とはいえ、--save-devでbabel-cli/binにあるのは、スクリプトなのですが…?
とりあえず、こんなスクリプトを用意。
app.js
"use strict"; class Calc { constructor() { } add(a, b) { return a + b; } } var calc = new Calc(); console.log("calc.add = " + calc.add(1, 3)); var outputFun = x => console.log(x); [1, 2, 3, 4, 5].forEach(outputFun);
※「babel-node」で動かす時に、「use strict」の記述が必要でした
babelコマンドでコンパイル後のソースが手に入るようですが…あんまり変わらなかったので実行する方にチェンジ。
babel-nodeコマンドを利用するようです。
$ babel-node app.js calc.add = 4 1 2 3 4 5
とりあえず、動いてくれました。
gulp+Browserify
続いて、gulpおよびBrowserifyと組み合わせてみます。
ドキュメントでは、gulpおよびBrowserify個々に組み合わせることができる記述があります。
今回は、Browserifyのtransformに与える方向で書いてみました。
つまり、こちらを採用します。
Browserify
では、書いていってみます。
npmプロジェクトを作成。
$ npm init
gulpをグローバルにインストール。
$ npm install -g gulp
「--save-dev」で、いくつかインストール。
$ npm install --save-dev gulp browserify babelify babel-preset-es2015 gulp-load-plugins gulp-util gulp-uglify gulp-sourcemaps vinyl-source-stream vinyl-buffer del
「babelify」がBabelとBrowserifyを合わせるためのモジュールです。その他のgulp-xxxなモジュールやvinyl-xxxなモジュールは、minifyやsoucemap作成などのために追加しています。
「babel-preset-es2015」を追加している理由は、後ほど。
また、ES6の追加機能をブラウザがサポートしていない場合は、Polyfillが必要だそうです。
$ npm install --save babel-polyfill
と、ここまで用意して、ソースコードの作成。
src/main.js
import "babel-polyfill"; import {Calc} from "./calc"; var calc = new Calc(); console.log("calc.add = " + calc.add(1, 3)); var outputFun = x => console.log(x); [1, 2, 3, 4, 5].forEach(outputFun);
src/calc.js
export class Calc { constructor() { } add(a, b) { return a + b; } }
先ほど、babel-nodeで動かしたサンプルを、import/exportを使って2分割してみました。
※babel-nodeでは、うまくimportが動かせませんでした…
また、コメントでご指摘いただいたのですが、babel-polyfillとBrowserifyを組み合わせる場合はアプリケーションのエントリポイントに
require("babel-polyfill");
もしくは
import "babel-polyfill";
と書いておけばよいようです。
To include the polyfill you need to require it at the top of the entry point to your application.
If you are using ES6's import syntax in your application's entry point, you should instead import the polyfill at the top of the entry point to ensure the polyfills are loaded first:
http://babeljs.io/docs/usage/polyfill/
今回はECMAScript 6スタイルにしました。
これらのコードを、Browserify+Babelでビルドするように、gulpの設定ファイルを作成。
gulpfile.js
var gulp = require("gulp"); var $ = require("gulp-load-plugins")(); var browserify = require("browserify"); var babelify = require("babelify"); var source = require("vinyl-source-stream"); var buffer = require("vinyl-buffer"); var del = require("del"); gulp.task("clean", function() { del.sync("dist/*") }); gulp.task("browserify", function() { browserify("src/main.js", { debug: true }) .transform(babelify, { presets: ["es2015"] }) .bundle() .on("error", $.util.log) .on("end", function() { $.util.log("browserify compile success."); }) .pipe(source("app.js")) .pipe(buffer()) .pipe($.uglify()) .pipe($.sourcemaps.init({ loadMaps: true })) .pipe($.sourcemaps.write("./")) .pipe(gulp.dest("dist")); }); gulp.task("default", ["browserify"]);
Browserifyのtransformとして、babelifyを加えているところと、presets-es2015を設定しているところがポイントです。
browserify("src/main.js", { debug: true }) .transform(babelify, { presets: ["es2015"] })
「presets-es2015」がないと、gulp-uglifyが失敗し、さらにブラウザ上でうまく動かなくなります…。
How to get sourcemaps for gulp+babel+browserify+uglify - Stack Overflow
これでgulpを実行すると
$ gulp [19:23:22] Using gulpfile /path/to/gulpfile.js [19:23:22] Starting 'browserify'... [19:23:22] Finished 'browserify' after 113 ms [19:23:22] Starting 'default'... [19:23:22] Finished 'default' after 12 μs [19:23:22] browserify compile success.
変換されたJavaScriptが出力されます。
dist/app.js
HTML上では、ビルド後のファイルを読み込むように設定します。
<script src="/dist/app.js"></script>
babel-nodeでimportが動かなかったり、BrowserifyとBabelを合わせた時にだいぶハマりましたが、なんとか動かせました。