ES2015

ES2015(旧 ES6)は、JavaScript 言語の大きな進歩です。これにより、ES5 で重要なボイラープレートを必要とするパターン向けの新機能と糖衣が提供されます。これには、クラス、アロー関数、モジュールが含まれます。このエピソードでは、ES2015 を最大限に活用して JavaScript ウェブアプリを構築するために使用するツールについて説明します。

Babel によるトランスパイル

JavaScript エンジンによる ES2015 のネイティブな実装は大きな進歩を遂げていますが、注意点が 1 つあります。現在、すべての機能セットを使用するには、コードを ES5 にトランスパイルして、現在のブラウザで解釈できるようにする必要があります。幸いなことに、Babel のようなツールがあればこのプロセスが簡単になります

ビルドプロセスでの Babel の使用

Babel を使用すると、ES2015 の機能を使用して記述された JavaScript を ES5 にトランスパイルして、現在これらの機能をサポートしていないブラウザで動作させることができます。ビルドプロセスに Babel を追加する手順は、次のとおりです。

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'));
});

Babel がトランスパイルできない一つの機能はモジュールです。ES6 のモジュールを使用すると、クラスを作成して、ファイル間でクラスをエクスポート / インポートできます。モジュールをトランスパイルするには、JavaScript を Browserify に渡してください。Browserify はファイルをマージしてから、Babelify(Browserify からの出力を処理できる Babel のバージョン)に渡します。

var babelify = require('babelify');
var source = require('vinyl-source-stream');
var browserify = require('browserify');

gulp.task('babelify', function() {
  browserify({ entries: './src.js', debug: true })
    .transform(babelify)
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('./dist/js/'));
});

複数の JavaScript ファイル

上記の例では特定のファイルを定義する必要があり、これが少し負担になります。Matt は、Gulp で次の処理を行い、末尾が .es6.js のファイルを検索してトランスパイルします。

var config = {
  src: 'src/scripts',
  dest: 'dist/scripts'
};
var es6FileGlob = '/**/*.es6.js';

var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
var glob = require('glob');
var path = require('path');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');

// Takes an array of bundles to run through browserify and babelify
function transpileES6Modules(browserifyFileEntries) {
  browserifyFileEntries.forEach(function(fileEntry) {
    var browserifyBundle = browserify({
        entries: [fileEntry.srcPath]
      })
      .transform(babelify);

    var finalStream = browserifyBundle.bundle()
      .on('log', plugins.util.log.bind(plugins.util, 'Browserify Log'))
      .on('error', plugins.util.log.bind(plugins.util, 'Browserify Error'))
      .pipe(source(fileEntry.outputFilename));

    return finalStream.pipe(gulp.dest(fileEntry.dest));
  });
}

// This takes a source path and finds all files ending
// with .es6.js and creates the bundles to run through browserify
// and babelify
function handleES6Scripts(srcPath) {
  var browserifyFileEntries = [];

  var es6Filepaths = glob.sync(srcPath + es6FileGlob);
  es6Filepaths.forEach(function(filepath) {
    var filename = path.basename(filepath);
    var directoryOfFile = path.dirname(filepath);
    var relativeDirectory = path.relative(
      srcPath,
      directoryOfFile);

    // Create an object and add to the browserify bundle array
    browserifyFileEntries.push({
      srcPath: './' + filepath,
      outputFilename: filename,
      dest: path.join(config.dest, relativeDirectory)
    });
  });

  transpileES6Modules(browserifyFileEntries);
}

gulp.task('scripts:es6', ['scripts:lint'], function(cb) {
  handleES6Scripts(config.src);

  cb();
});

lint チェックとスタイル チェック

コードの lint チェックを行い、考えられる問題やスタイルへの準拠状況を確認する場合、いくつかの選択肢があります。

JSHint と JSCS

JSHintJSCS は、今日の JavaScript スタイル チェックで最もよく使われるツールです。

JSHint は、コード内の考えられる問題をハイライト表示し、一般的に不適切と見なされるパターンを特定します。

JSCS はコードのスタイルを確認します。これには、タブまたはスペースのみが使用されていること、スペースが一貫した場所に配置されているかどうかなどが確認されます。

ES2015 コードで JSHint と JSCS を使用するには、"esnext": true.jshintrc ファイルと .jscsrc ファイルに追加する必要があります。

ESLint

ESLint は代替のリンターとスタイル チェッカーです。このツールは多くの動きを考慮し、JavaScript が記述されている環境を示す機能や、特定の問題のエラーレベルや警告レベルを設定する機能など、JSHint よりも優れた機能を備えています。

ESLint は完全にカスタマイズ可能で、カスタム lint ルールが用意されているため、構成ファイルを介して、オプションのオンとオフを切り替えられるかどうかを指定できます。また、React を使用している場合、ESLint は JSX でも動作します。

ビルドプロセスで ESLint を設定するのもそれほど難しくありません。

var gulp = require('gulp'),
    eslint = require('gulp-eslint');

gulp.task('lint', function () {
    return gulp.src(['js/**/*.js'])
        // eslint() attaches the lint output to the eslint property
        // of the file object so it can be used by other modules.
        .pipe(eslint())
        // eslint.format() outputs the lint results to the console.
        // Alternatively use eslint.formatEach() (see Docs).
        .pipe(eslint.format())
        // To have the process exit with an error code (1) on
        // lint error, return the stream and pipe to failOnError last.
        .pipe(eslint.failOnError());
});

gulp.task('default', ['lint'], function () {
    // This will only run if the lint task is successful...
});

Babel チームでは、babel-estlint を管理しています。これは、ESLint を使用して有効な Babel コードを lint チェックできるツールです。ESLint はカスタム パーサーをサポートしていますが、Babel によってサポートされている構文の一部は ESLint で直接サポートされていないため、さらに柔軟性が必要な場合は、別のオプションを使用できます。これを設定するには、.eslintrc ファイルの parser セクションをカスタマイズします。

{
  "parser": "babel-eslint",
  "rules": {
    "strict": 0
  }
}

Dan Abramov 氏は、Lint Like It's 2015 で、ESLint と babel-eslint のセットアップについて素晴らしい執筆を行っています。また、Sublime Text での ES2015 lint サポートのワークフローに SublimeLinter-eslint を統合する方法についても説明します。

どれを使用すればよいですか。さまざまな方法を試して、自分に最適な方法を探してください。

ES2015 構文のハイライト表示

もちろん、ES2015 コードの構文を正しくハイライト表示する必要があります。パッケージ管理からインストールできる babel-sublime を使用できます。セットアップするときは、ハイライト表示が必要なファイルのデフォルトとして設定することをおすすめします。これには JS も含まれますが、React を使用する場合は JSX も含まれる可能性があります。

ドキュメント ES2015

これまで、私たちは JavaScript コードの文書化に JSDoc を多用してきました。残念ながら ES2015 のサポートに関して未解決の問題があります(JSDoc 3 で対処されているため)。ただし、追いつくのを待っている間、利用可能な代替手段は増え続けています。そのような選択肢の 1 つが ESDoc です。Jonathan Creamer 氏は、それに関する最近の執筆資料を読む価値があります。

Babel を使用した Gulp.js ファイルの作成

ビルドプロセスで Gulp を使用している場合、Babel でサポートされている任意の構文を使用して Gulpfile を作成できるようになりました。これは Web Starter Kit で行っており、設定は比較的簡単です。最新バージョンの Gulp と Gulp CLI を使用して、gulpfile.js の名前を gulpfile.babel.js に変更すると、Gulp が Babel を使用して ES2015 の gulpfile を自動的に解釈してトランスパイルします。

ES2015 のお気に入りの機能

モジュール

モジュールを使用すると、あるファイルから値、関数、クラスをエクスポートし、別のファイルにインポートできます。

export function exampleFunction() {
  console.log('I\'m an example. #TrueStory');
}



import { exampleFunction } from './example-function';
import BaseController from './base-controller';

export default class ExampleController extends BaseController {
  constructor() {
    super();

    exampleFunction();
  }

  doSomething() {
    console.log('What should I do? Change the DOM? Print a dancing shark to the console?');
  }
}

このサイトでは、モジュールの優れた例と説明をいくつか紹介しています

テンプレート文字列

テンプレート文字列を使用すると、文字列のポートを変数に置き換えることができます。

// Simple string substitution
var name = "Brendan";
console.log('Yo, ${name}!');

// => "Yo, Brendan!"

テンプレート文字列の長所は、置換が JavaScript の実行であり、関数やインライン式を使用できることです。

var a = 10;
var b = 10;
console.log('a+b = ${a+b}.');
//=> a+b = 20.

function fn() { return "I am a result. Rarr"; }
console.log('foo ${fn()} bar');
//=> foo I am a result. Rarr bar.

詳しくは、Addy によるこの便利なブログ投稿をご覧ください。

省略形オブジェクト リテラル

オブジェクト リテラルを使用すると、オブジェクトに必要なキーと変数の名前が同じである場合、オブジェクトの作成時にキーと値を定義する必要がなくなります。

意味:

function createObject(name, data) {
  return { name: name, data: data };
}

これは、次のようになります。

function createObject(name, data) {
  return { name, data };
}

計算されたプロパティ名

ES2015 のこの機能により、オブジェクトにプロパティ名を動的に作成できます。Mozilla ドキュメントは優れた情報源です。この優れた例をご覧ください

var a = {
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
  ["foo" + ++i]: i
};

console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3

太い矢印関数

ファットアロー関数を使用すると、次のような関数を簡単に記述できます。

button.addEventListener('click', function(event) {
  console.log('The button has received a click', event);
});

これは、次のようになります。

button.addEventListener('click', (event) => {
  console.log('The button has received a click', event);
});

ファットアロー関数を使用する優れた点は、構文が短いことを除き、オブジェクトのスコープが囲み文と同じであることです。つまり、関数で .bind(this) を呼び出したり、これに相当する var を作成したりする必要はありません。

MDN には他にも多くの例があります。

Addy の ES6 ツール リポジトリ

Addy さんは ES2015 ツールのリストの管理に熱心に取り組んでいます。上記のツールが自分に合わない場合、Gulp ではなく Grunt を使用しているかもしれません。これで答えが見つかります。

https://github.com/addyosmani/es6-tools

上記のリンクには、単体テストなどに役立つ追加の Babel ツールへのリンクも含まれています。

読みたい本

ES2015 の詳細については、オンラインで無料でご確認いただける書籍が 2 件あります。ECMAScript 6 を理解する(著者: Nicholas C. Zakas および Exploring ES6(Axel Rauschmayer 博士)

バベルの塔

コマンドラインでの ES2015 機能に興味がある場合は、tower-of-babel で一連の演習を行うことができます。どれも Babel を使って説明します。

参考になるその他のリソース: