ES6を導入したいRailsエンジニアの覚書き
選定候補
- CoffeeScript
- 現状使用している
- Railsとの相性がよい(デフォルトでサポートされている)
- ECMAScript 6(以下、ES6)
- 次期JavaScriptの標準仕様
ES6はいつ勧告されるの?
- 2015年6月予定
- つまり、仕様はまだ固まっていない(が、ほぼほぼ固まっていると言って良いと思われる)
ES6の機能
- es6featuresで概要を一覧できます
- Mozillaが出している非公式のES6ドラフト仕様書はこちら
- 「2015 年の JavaScript と babel の話」や「HELLO, ES6 ~これから迎えるJSのミライ~」もわかりやすかった
ES6とCoffeeScriptの機能比較
es6featuresに記載される機能のCoffeeScriptでの実装状況を一覧表にしてみました。
ES6の主な新機能 | CoffeeScriptでの実装の有無 | メモ |
---|---|---|
arrows | ○ | 引数や括弧を省略可能 |
classes | ○ | Coffee: 括弧なしで関数を呼べる, ES6: getterとsetterが使える |
enhanced object literals | △ | {foo: foo}の省略記法はCoffeeにも実装済み |
template strings | ○ | |
destructuring | ○ | |
default + rest + spread | ○ | |
let + const | × | |
iterators + for..of | × | |
generators | ○ | CoffeeScriptではfunction* は不要、yield を呼び出すだけ |
unicode | × | |
modules | browserifyなどがこの問題を解決している | |
module loaders | × | |
map + set + weakmap + weakset | × | |
proxies | × | |
symbols | × | |
subclassable built-ins | × | |
promises | × | bluebirdやjQuery.Deferredなどを使用すれば可能, ただしjQuery.DeferredのDefferdとPromiseは正確には別物 |
math + number + string + array + object APIs | × | |
binary and octal literals | ○ | |
reflect api | × | |
tail calls | × |
ref: es6features
余談: サンプルコード
サンプルコードを載せておくので雰囲気を感じてください。 1文字でも短く書きたいという人は、CoffeeScriptの方が好きかもしれません。
class Person constructor: (@firstName, @lastName) -> name: -> "#{@first_name} #{@last_name}" setName: (name) -> names = name.split " " @firstName = names[0] @lastName = names[1] blake = new Person "Blake", "Williams" blake.setName("Blake Anderson") console.log blake.name()
ES6
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } get name() { return this.firstName + " " + this.lastName; } set name(name) { var names = name.split(" "); this.firstName = names[0]; this.lastName = names[1]; } } var blake = new Person("Blake", "Williams"); blake.name = "Blake Anderson" console.log(blake.name);
refs: Replace CoffeeScript with ES6
ES6のブラウザ実装の対応状況
ES6をプロジェクトで使うには?
主な方法は3つある。
ES6がサポートされているブラウザのみをサポートブラウザとする
- compatibility tableを見る限り現実的ではない
Polyfillを使用する
- ex: ES6-style Promisesのpolyfill
- 機能ごとにpolyfillを選定する必要があるためコストが高そう
- HTML5 Cross Browser Polyfills
- トランスパイラを使用する
- babel がデファクトスタンダード
- @joker1007 さんも個人プロジェクトで採用しているっぽい
Railsでbabelを使う
Sprockets で使う方法
sprockets-es6あたりのgemを使えばよさそう。 ただ、あまりStarが集まっていなかったりするので、このやり方を試している人が少ないのかもしれない。
ref: Ruby Toolboxで「es6」と検索した結果
gulp などで使う方法
だいたいこんな感じでgulpfileを書けばいけそう。 @yachibit が試してみたvanilla appも参考になるかも。
var gulp = require("gulp"); var sourcemaps = require("gulp-sourcemaps"); var babel = require("gulp-babel"); var concat = require("gulp-concat"); gulp.task("default", function () { return gulp.src("src/**/*.js") .pipe(sourcemaps.init()) .pipe(concat("all.js")) .pipe(babel()) .pipe(sourcemaps.write(".")) .pipe(gulp.dest("dist")); });
ref: http://magazine.rubyist.net/?0050-ECMAScript2015
ライブラリのサポート
標準JavaScriptでサポートされているライブラリがCoffeeScriptやES6で使用できるとは限らない。 ES6は標準なので、将来的にはCoffeeScriptと比較するとES6関連のライブラリの方が充実する可能性が高いと考えられる。
- ex: power-assert
- CoffeeScripで使用するにはespower-coffeeが必要
- ES6(babel)で使用するにはbabel-plugin-espowerが必要
- ES6についてはこの辺が参考になりそう
学習コスト
CoffeeScriptを採用する場合
- 既存のメンバーや世間のRailsエンジニアはCoffeeScriptに慣れているのでCoffeeScriptを使用する際の学習コストは殆ど無い
- CoffeeScriptに慣れていないメンバーがジョインする際に学習コストが発生する可能性がある
- 既存の書籍やライブラリのサンプルコードは普通のJavaScriptで書かれることが多いため、脳内コンパイルする必要がある
ES6を採用する場合
- ES6を覚える必要があるが、基本的にはJavaScriptなのでそれほど難しくはないと思われる
- 標準仕様なので、新規にジョインするメンバーも使える可能性が高い
- 勧告前なのでそれほど普及しているわけではないと思うが
既存コードの活用
- gulpとbabelをうまく使えば、CoffeeScriptで書かれたコードとES6で書かれたコードをそれぞれ別々でES5にトランスパイルすることが可能なので、共存させることも可能
まとめ
個人的にはES6を推したい
ES6を推したい理由
- ES6は大規模開発をしやすくする機能や、関数型プログラミングの概念が取り入れられているため、よりモダンな開発が可能となる
- 標準仕様であるため、ライブラリのサポートや書籍等の情報がES6に優位に進んでいくと思われる
- gulpやbabelの力を借りれば、既存のCoffeeScriptのコードも活用することができる
- babelはReactとの相性がいい
- babelにはJSX transformerが同梱されている
懸念点、課題
- チームでのコーディングルール(変数宣言、プロトタイプベースのクラスは使わない等)
- 既存の開発メンバーがES6を学習する必要がある
- 好みの問題ではあるが、CoffeeScriptと比較すると、varや括弧等の記述が増えるため、コード量が増える
るびまでの @yosuke_furukawa さんのまとめが大変わかりやすかったので併記しておきます。
JavaScript に class や module の考え方が入り、適切な単位でモジュールとクラスを分割して設計することができるようになりました。また let や const で変数の生存範囲を限定する事ができるようになりました。これらの機能は大規模なアプリを開発する時やライブラリを作る際の助けになるはずです。
また、generator/iterator/Promise といった関数型プログラミングの概念が導入され、さらに末尾呼び出し最適化といった副作用を少なくする記述方法ができるようになりました。ES6 には ES5 までの考え方にはないモダンな機能が入っています。
おまけ
- AltJSの選び方フローチャートは試しにやってみると面白いかも
- es6fiddleを使えば、ブラウザ上でお試しできます
- GitHub の ATOM が CoffeeScript で書かれているのはどうなの?
- @yosuke_furukawa さんが開発されたES6の学習ツール tower-of-babel