Wercker CLI で最新フロントエンド開発環境を Docker 化してみよう

最新のフロントエンド開発環境を整備してチュートリアルなどを実行するのは面倒、ということは実はなくて、Node.js さえインストールしてあれば `npm install && npm start` で大概は済む話です。とはいえ、何事も進化の早い当節のこと、開発マシンにインストールする Node.js のバージョンを１つに決めることすら難儀なことです。

そこで Docker コンテナー上に Node.js を含めた必要な開発環境を全て構築してしまえば開発マシンの汚れを気にすることなく好みのツールをセレクトして開発を開始することができます。また、Docker 化することで開発環境の整備方法が文書化され、いつでもどこでも誰にでも再現可能になります。

今回は Docker の長々しいコマンドラインやあまり美しいとはいえない Dockerfile を回避するために [Wercker]( http://www.wercker.com/ ) CLI を利用してみましょう。

## 事前準備

1. Docker をインストールします。
2. Wercker CLI をインストールします。<br>[Releases · wercker/wercker]( https://github.com/wercker/wercker/releases ) から適切なバイナリをダウンロードして `chmod +x` して PATH の通ったディレクトリにコピーするだけですが、現時点（2017年夏）での最新バージョン 1.0.882 のバグを避けるために 1.0.643 の利用をおすすめします。

## react-scripts の利用

[フロントエンド開発の基本知識（2017年夏）]( http://qiita.com/norioxkimura/items/1dc1cea1c0a8ea7adf31 )に書いたように、モダンなフロントエンド開発では Babel, TypeScript, webpack, Browserify といった Node.js 製ツールを使います。

これらをちゃんと設定するのは面倒なので、今回はレディーメイドのオススメ設定を提供してくれるツールを使ってみます。それが react-scripts です。名前に <q>react</q> が含まれていますが、特に React を使う必要はありません。どのような環境を提供してくれるかは [User Guide]( https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md ) に詳しく書かれています。

まず package.json を用意します。

```json:package.json
{
  "devDependencies": {
    "react-scripts": "1.0.10"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build"
   }
}
```

開発する HTML と JavaScript を用意します。react-scripts の定めで、それぞれ public/index.html, src/index.js に置くことが決められています。

```html:public/index.html
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>No Title</title>
</head>
<body>
  <div id='app'></div>
</body>
</html>
```

```js:src/index.js
setInterval(() => {
    const text = document.createTextNode('*');
    document.getElementById('app').appendChild(text);
}, 1000);
```

さて、wercker.yml を用意して Docker 化してみましょう。

```yaml:wercker.yml
dev:
   box:
      id: node:6
      ports: [ 3000 ]
   steps:
    - npm-install
    - internal/watch:
         reload: false
         code: |
            npm start
```

プロジェクトの全体像は以下のようになります。

```text
.
├── package.json
├── public/
│   └── index.html
├── src/
│   └── index.js
└── wercker.yml
```

実行してみましょう :

```shell-session
$ wercker dev --expose-ports
```

初回の実行では `npm install` を実行して node_modules にファイルをダウンロードするため遅いですが、次回以降はダウンロードは発生しないため早くなります。

ブラウザで `http://localhost:3000/` を開くとアプリケーションが表示されます。index.js で ES2015 規格のアローファンクション `() => ...` を記述していますがちゃんと動作しています。index.html に index.js を読み込む `<script>` が無いにもかかわらず index.js が動作していることもわかります。webpack によって自動的にバインドされているのです。

ブラウザーを開いたまま index.js や index.html の内容を編集すると、自動的に再トランスパイルされ、ブラウザの内容もリロードされます。

開発サーバーを停止するには Ctrl-C を入力します。

## 既存チュートリアルの Docker 化

今度は既存のチュートリアルを Wercker CLI を使って Docker 化してみましょう。例に取るのは [react-js-tutorials/1-basic-react at master · learncodeacademy/react-js-tutorials]( https://github.com/learncodeacademy/react-js-tutorials/tree/master/1-basic-react ) です。

まずクローンします :

```shell-session
$ git clone 'https://github.com/learncodeacademy/react-js-tutorials.git'
$ cd react-js-tutorials/1-basic-react
```

wercker.yml を用意します :

```yaml:wercker.yml
dev:
   box:
      id: node:6
      ports: [ 8080 ]
   steps:
    - npm-install
    - internal/watch:
         reload: false
         code: |
            npm run dev
```

実行してみます :

```shell-session
$ wercker dev --expose-ports
```

しかし、ブラウザでアクセスしても動きません。これは、このチュートリアルで起動する開発サーバーが、localhost のポートのみをリッスンしていて、外部からアクセス出来ないためです。これを 0.0.0.0 にバインドするように変更しなければなりません。

このために package.json の npm-scripts を変更します。

```json:package.json
{
  "scripts": {
    "dev": "webpack-dev-server --content-base src --inline --hot --host 0.0.0.0",
  }
}
```

package.json の `.scripts.dev` のコマンドラインの最後に ` --host 0.0.0.0` を足しました。今度はうまくいきます :

```shell-session
$ wercker dev --expose-ports
```

としてブラウザーで http://localhost:8080/ を開いてください。