読者です 読者をやめる 読者になる 読者になる

破いて捨てたノート

Webやテクノロジーやそれ以外に関する思いつき

ES6を導入したいRailsエンジニアの覚書き

JavaScript ES6 Rails

選定候補

ES6はいつ勧告されるの?

  • 2015年6月予定
    • つまり、仕様はまだ固まっていない(が、ほぼほぼ固まっていると言って良いと思われる)

ES6の機能

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 × bluebirdjQuery.Deferredなどを使用すれば可能, ただしjQuery.DeferredのDefferdとPromiseは正確には別物
math + number + string + array + object APIs ×
binary and octal literals
reflect api ×
tail calls ×

ref: es6features

余談: サンプルコード

サンプルコードを載せておくので雰囲気を感じてください。 1文字でも短く書きたいという人は、CoffeeScriptの方が好きかもしれません。

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つある。

  1. ES6がサポートされているブラウザのみをサポートブラウザとする

  2. Polyfillを使用する

  3. トランスパイラを使用する

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関連のライブラリの方が充実する可能性が高いと考えられる。

学習コスト

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 までの考え方にはないモダンな機能が入っています。

おまけ