※当サイトの記事には、広告・プロモーションが含まれます。

ECMAScript 2015(ECMAScript 6th edition)とトランスパイラとAltJS(Alternative JavaScript)と

ECMAScriptとは?

JavaScriptは1995年にWebで実行できるスクリプト言語として開発されたそうですが、ブラウザベンダーによる独自の拡張が多く互換性が低かったので、ブラウザ間で動いたり動かなかったりがあったのではないかと。

そこで、Ecmaインターナショナルが中心となり、JavaScriptの中核仕様を抜き出して標準化したのがECMAScriptのようです。

ECMAScript 2015(ES6)の概要と次世代JavaScriptの新たな機能 | HTML5Experts.jp

言語仕様を整理していきましょうということみたいです。

ES2015(ES6)で追加された仕様

ECMAScript 6th editionの6を取ってECMAScript 6(ES6)と呼ばれていますが、正確な呼称はECMAScript 2015(ES2015)というようです。

  • let・constキーワードによる変数宣言
  • classキーワードによるクラス宣言
  • 関数の引数のデフォルトパラメータ(Default Parameters)
  • 関数の可変長引数(Rest Parameters)
  • アロー関数(Arrow Functions)
  • ジェネレータ関数(Generator Functions)
  • 配列展開(Array Spread)
  • 分割代入(Destructing Assignment)
  • 文字列のテンプレートリテラル(Template Strings)
  • importとexportによるモジュール構文(Module)

など、かなり新しい文法が追加されています。

ブラウザのJavaScriptエンジン(JavaScript runtimeとも言う?)

ブラウザがJavaScriptを実行できるのは、JavaScript runtimeがECMAScriptの構文を解釈して実行しているためのようです。

ただ、このJavaScript runtimeがブラウザごとに異なるようです。

ブラウザ レンダリングエンジン JavaScript runtime
Chrome Blink V8
Opera Blink V8
Safari Webkit JavaScript(Nitro)
PhantomJS Webkit V8
Firefox Gecko SpiderMonkey
IE Trident Chakra

PhantomJSと各ブラウザのJavascriptエンジンまとめ | tsuchikazu blog 

つまり、ES6使いたいけどES5までしか対応できてないブラウザでは、ES6が使えないことになります。

でも、ES6使って開発したいという場合、

完全ではないですが、Babel(旧6to5)などのトランスパイラやpolyfillライブラリを活用する方法があります。

トランスパイラ

新しい文法を使ったソースコードをES5 または ES3 までの文法に置き換えるソースコード変換ツール。

  • Babel
  • buble
  • Traceur Compiler
  • Rollup

など種類が結構あるようです。 

AltJS(Alternative JavaScript

AltJS(Alternative JavaScript)とは、その名の通りJavaScriptの代替言語です。JavaScriptと同等以上の機能を提供している言語ということらしいです。

コンパイルされることでJavaScriptのコードになるようです。

WEB+DB PRESS Vol.87のECMAScript 6特集を読んだ(+TypeScript) - dackdive's blog

レトロエンジニアのための近代Webフロントエンド事情 - Qiita

ES6開発環境を作ってみる

Node.jsがインストールされている必要があり、npmコマンドも必要になってきます。 Node.jsをインストールし、npmコマンドで必要なものをインストールしていく感じでしょうか。 

 

  • Node.js
    • Babel
    • Polyfill
    • webpack
    • Mocha
    • Karma

⇩  下記サイトが詳しいです。 

BabelでES6で書いて、webpackでビルドして、mochaでテスト書いて、power-assertでassertの出力を見やすくして、karmaで複数ブラウザのテストを自動化して、カバレッジを出力するようにした - UUUM攻殻機動隊

いきなりハマる

Babel6になって、いろいろ仕様が変わったようで、導入の仕方が変わったようです。

これを知らずに、かなりハマりました。

babel 6 やってみる - Qiita

babel6での変更点 Gulp・Webpackの設定 - Qiita

まずは、コマンドプロンプトを開きます。babel-cliをインストールします。今回は管理者ではなく、ユーザーでコマンドプロンプトを開いてます。

    npm install --global babel-cli

f:id:ts0818:20170109134553j:plain

下記コマンドでbabelのバージョン情報が表示されれば、インストール成功です。 

babel --version

npmでnodeのモジュール(今回だとbabel-cli)をグローバルにインストールすると、

C:\Users\ユーザー名\AppData\Roaming\npm\node_modules

にnode_modulesというフォルダの中にモジュールが追加されていくので、環境変数にパスを追加しておくと nodeのrequire先のトラブルが解消できるようです。

今回は、設定しませんでしたが設定しておきたいと思います。

Windowsのnode.jsでrequire検索パスの初期値を自動設定する - Null and void

 

次に、package.jsonファイルを作成します。プロジェクトは package.json で管理することが一般的のようなので、ない場合は作成しておけば間違いないかと。

適当な場所にフォルダを作成(今回はC:¥ES6を作成)しておいて、cdコマンドでそのフォルダ(プロジェクト)の場所まで移動したら、

    npm init

コマンドを実行します。対話式で プロジェクト名やユーザー名, バージョン番号, その他諸々聞かれますが、今回はEnter連打で。これでpackage.jsonファイルが用意されます。

「babel-preset-es2015」をインストール

BabelにES2015のコンパイルの処理を行わせる「babel-preset-es2015」というプリセットをプロジェクトにインストールします。--save-devはinstallしたlibraryの情報を自動でpackage.jsonに書いてくれるoptionのようです。

    npm install babel-preset-es2015 --save-dev

f:id:ts0818:20170109170330j:plain

.babelrcファイルの準備

.babelrcという設定ファイルを用意し、そこにBabelでさせたい処理をプリセットやプラグインとして登録しておく必要があります。

    echo '{ "presets": ["es2015"] }' > .babelrc

このような、構成になっていればOK。

f:id:ts0818:20170109134054j:plain

このフォルダ(プロジェクト)に、ES6で記述したファイルを作成し保存します。

"use strict";

class User {
  constructor(name) {
    this.name = name;
  }

  greet() {
    return 'Hello, My name is ' + this.name;
  }
}

var bob = new User("Bob");
bob.greet();

f:id:ts0818:20170109141342j:plain

ファイルを作成したら、ES5に変換したファイルを下記コマンドで作成します。(トランスパイル実行)

    babel test.js -o test-es5.js

test-es5.jsファイルが作成されました。 

f:id:ts0818:20170109141849j:plain

ファイルの中身を確認すると、ES5に変換されてるようです。 

"use strict";

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var User = function () {
  function User(name) {
    _classCallCheck(this, User);

    this.name = name;
  }

  _createClass(User, [{
    key: "greet",
    value: function greet() {
      return 'Hello, My name is ' + this.name;
    }
  }]);

  return User;
}();

var bob = new User("Bob");
bob.greet();

Babelでトランスパイル成功です。

Polyfillのインストール

Babel でトランスパイルすることで、古いブラウザでも動作する Javascript を出力できるようになったのですが、古いブラウザの標準オブジェクトの中には ES6 に対応していないものがあります。 そのために標準オブジェクトを拡張する Polyfill を導入するようです。

    npm install babel-polyfill --save-dev

f:id:ts0818:20170109143606j:plain

標準オブジェクトを拡張することは、既存の環境と互換性を失うことになります。Polyfill を導入するときは、標準オブジェクトを拡張していることをちゃんと認識したうえで使う必要があるようです。

webpackのインストール

webpack は WebApp に必要なリソースの依存関係を解決し、アセット(配布物)を生成するビルドツール(要するにコンパイラ)です。JavaScript だけでなく、CoffeeScript や TypeScript、CSS 系、画像ファイルなどを扱うことができます。

webpack で始めるイマドキのフロントエンド開発 - Qiita

ということで、インストールします。webpack は様々形式のデータを扱うのに、プラグイン形式で対応しており、babel を使う場合は babel-loader を使います。webpackはグローバルでインストールします。

npm install -g webpack

f:id:ts0818:20170109170331j:plain

npm install babel-loader --save-dev

f:id:ts0818:20170109170332j:plain

interpret に対応しているツール(webpackはinterpretをロードしている)に関しては、babel-register をインストールすれば、もれなく ES6 にも対応できるようです。

npm install babel-register --save-dev

webpackの設定ファイル(通常はwebpack.config.js)をプロジェクト直下に作成します。

webpack.config.babel.jsという名前にしておくと、babelなコードとして読んでくれる(webpackはinterpretをロードしているため。このbabelにも.babelrcの内容は適用される)ようです。

f:id:ts0818:20170109151516j:plain

 

const path = require("path")

module.exports = {
    // どのファイルをビルドするのかを指定。複数可。
    entry: {
      test: './src/test.js',
      main: './src/main.js',
    },
    // 出力するファイル名と出力先パス
    output: {
        path: path.join(__dirname + '/web'),
        filename: '[name].js'
    },
    // トランスパイルされる前のjsファイルとトランスパイル後のjsファイルのソースマップ
    devtool: 'inline-source-map',
    // module
    module: {
      loaders: [{ 
        // .js のファイルに対して
        test: /\.js$/,
        include: [
          path.join(__dirname + '/src'),
          path.join(__dirname + '/test'),
        ], 
        exclude: /node_modules/,
        loader: 'babel-loader',  // loader でローダの指定。( babel-loader を使用して babel でトランスパイルする)
      }]
    }
}

フォルダの構成を変更します。srcフォルダの中にES6で記述されたtest.js、main.jsを作成しておきます。webフォルダにはindex.htmlを作成し、

<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script src="main.js"></script>
    <script src="test.js"></script>
  </body>
</html>    

としておきます。 

f:id:ts0818:20170109175309j:plain

webpackコマンドコマンドを実行します。

    webpack

f:id:ts0818:20170109175643j:plain

index.htmlをブラウザで表示し、デベロッパーツールの『console』を確認します。

f:id:ts0818:20170109184157j:plain

 何故か、main.jsの内容は読み込まれてますが、test.jsの内容が反映されない(涙)。

MochaとKarmaについてはまたの機会にトライしてみたいと思います。

追記

test.jsの内容が間違ってました。returnじゃConsoleに表示されないってことですね。 

訂正前のtest.js

"use strict";

class User {
  constructor(name) {
    this.name = name;
  }

  say() {
    return 'Hello, My name is ' + this.name;
  }
}
var bob = new User("Bob");
bob.say();

訂正後のtest.js

"use strict";

class User {
  constructor(name) {
    this.name = name;
  }

  say() {
    console.log('Hello, My name is ' + this.name);
  }
}
var bob = new User("Bob");
bob.say();

f:id:ts0818:20170109212545j:plain

⇩  フォルダ構成など維持したままコンパイルする方法は下記サイトへ

Webpackで複数のファイルをそのままバンドルする - はらへり日記

 

今回はこのへんで。