ES2015のモジュールをBrowserifyとBabelifyでビルドしてクライアントで読み込んでみる

# 概要

今更ES2015やES2015(ES6)からES5（現行）のJavaScriptに変換してくれるBabelとか

ES2015のモジュールを使うのにはBrowserifyやBabelifyというものを使うといいらしいなどがわかった

ビルドする際に色々とエラーが出て詰まったのでメモ

# ES2015とは

ECMAScript 2015（ES2015)のことらしい

ES2015自体はJavaScriptそのものではなく、あくまで言語仕様とのこと

JavaScriptはECMAScriptという言語仕様に基づいた言語のひとつ

ECMAScript 2015はECMAScript 6th editionでECMAScript 6(ES6)とも呼ばれる

つまり ECMAScript 2015(ES2015) = ECMAScript 6(ES6)

その前がECMAScript 5(ES5)で、ES6対応していないブラウザの主流はES5

# Babelとは

ブラウザにはJavaScriptを実行する為にJavaScriptエンジンが搭載されているが、現行のブラウザの全てはES2015に対応しているわけではない

その為、そのままではES2015で追加された言語仕様は使用できない

せっかく追加された機能をブラウザの対応を待って使えないのは不便すぎるのは新しいES2015の機能を現行の対応していないブラウザでも使えるようにしたい

使えるようにする為にES2015(ES6)の文法で書かれたJavaScriptをES5に変換して、実行できるように変換してくれるのがBabel

# Browserifyとは

サーバーサイドJavaScript動くで使える機能やツールはブラウザに実装されているJavaScriptでは実行できない為、それをブラウザで実行できるJavaScriptに変換してくれるライブラリ

サーバーサイドJavaScriptでモジュール機能を使うためのexport/requireはブラウザにはない機能なので、ブラウザでも使えるようにする為にBrowserifyで変換する

# Babelifyとは

ES2015からES5にJavaScriptを変換する為のツールBabelをBrowserifyで使えるようにする為のライブラリ

# ES2015でモジュールを用意する

プロジェクトを用意する

```bash
mkdir es2015-module-build-test
cd es2015-module-build-test
touch index.html
vi index.html
```

ビルド後にクライアント側でJSを読み込む為のファイルを作る

```html
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ES2015モジュールのビルド</title>
</head>
<body>
</body>
</html>
```

```bash
mkdir scripts
touch ./scripts/export.js ./scripts/import.js
```

```javascript
// export.js
export default class {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    get firstName() {
        return this._firstName;
    }
    set firstName(value) {
        this._firstName = value;
    }
    get lastName() {
        return this._lastName;
    }
    set lastName(value) {
        this._lastName = value;
    }
    getName() {
        return this.lastName + ' ' + this.firstName;
    }
}
```

```javascript
import Member from './export';

let member = new Member('Hoge', 'Tarou');
console.log(member.getName());
```

ファイルが用意できたが、モジュール機能を使う為のexport/importはそのままでは利用できないので、ブラウザで実行できる形式に変換する必要がある

# ES2015のモジュールをブラウザで使用できるようにビルドする

ES2015の文法で書いたJSをブラウザで実行できるようにサーバーサイドJSのライブラリを利用して変換してやる

下記を実行すると対話形式で色々聞かれるが入力必須ではないので全部EnterでOK

```bash
npm init
```

実行するとpackage.jsonがプロジェクトフォルダにできる

これでこのプロジェクト内でnpmのライブラリをインストールしたりできるようになる

次は下記コマンドでBrowserifyとBabelifyを導入する

Browserifyはグローバルにbabbelifyはローカルにインストールする

```bash
npm install -g browserify
npm install -D babelify
```

ES2015のモジュールをES5で使えるようにする為のライブラリを導入できたので、下記コマンドでビルドを実行してみる

`-t`オプションは「--transform, -t  Use a transform module on top-level files.」というわけでどうやって変換するかをオプションで指定するらしい

下記はbabelifyでES2015のpresetsを使って変換してくださいという意味

babelifyはbrowserifyでbabelを使えるようにしたライブラリ

変換対象は`/scripts/import.js ./scripts/export.js`で変換後のソースが`./scripts/app.js`に出力される

```bash
browserify ./scripts/import.js ./scripts/export.js -t [ babelify --presets es2015 ] -o ./scripts/app.js
Error: .presets must be an array, or undefined while parsing file:
```

実行すると上記のようなエラー

調べるとes2015の部分を[]で囲っている記法が出てきたので再度試す

```bash
browserify ./scripts/import.js ./scripts/export.js -t [ babelify --presets [es2015] ] -o ./scripts/app.js
Error: Cannot find module 'babel-preset-es2015' from
```

エラーメッセージが変わる

presetsがそもそも用意されていないのが原因では？と下記を実行

```bash
npm install -D babel-preset-es2015
npm WARN deprecated babel-preset-es2015@6.24.1: 🙌
Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!
```

インストールできたがどうやら非推奨らしいので、`babel-preset-env`を入れ直す

```bash
npm uninstall -D babel-preset-es2015
npm install -D babel-preset-env
```

presetsをenvに変更して、再度実行してみる

```bash
browserify ./scripts/import.js ./scripts/export.js -t [ babelify --presets [env] ] -o ./scripts/app.js
TypeError: Cannot read property 'bindings' of null while parsing file:
```

上記のようなエラーが発生が、Babelのissueに下記のようなものが上がっていた

[env preset breaks on class in v7 alpha 20 #6186](https://github.com/babel/babel/issues/6186)

その中のコメントに下記のバージョンを使ってみるといいという情報が

>@bowdenk7 you will want to use babel-preset-env@2.0.0-alpha.20

ということで参考にしてバージョンを変えて実行してみる

```bash
npm uninstall -D babel-preset-env
npm install -D babel-preset-env@2.0.0-alpha.20
browserify ./scripts/import.js ./scripts/export.js -t [ babelify --presets [env] ] -o ./scripts/app.js
```

自分の環境ではここまでで上手くいき、`./scripts/app.js`がビルドされた

# ビルドされたJSをブラウザで読み込む

HTMLファイル内でビルドされたJSを読み込めば実行される

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ES2015モジュールのビルド</title>
</head>
<body>
<script src="scripts/app.js"></script>
</body>
</html>
```

result

```text
Tarou Hoge
```

# ソース一式

[ここにあげときました](https://github.com/trewa-nek9585/es2015-module-build-test)

# 参考リンク

[ECMAScript 2015のブラウザ対応状況と実践投入に向けて](https://html5experts.jp/1000ch/16995/)

[JavaScriptのモジュール管理(CommonJSとかAMDとかBrowserifyとかwebpack)](https://tsuchikazu.net/javascript-module/)

[npm とか bower とか一体何なんだよ！Javascript 界隈の文脈を理解しよう](https://qiita.com/megane42/items/2ab6ffd866c3f2fda066)

[JavaScriptにおけるモジュールとimport/exportの使い方](http://analogic.jp/module-summary/)