ゼロから始めるJavaScript生活

（訳者注: これは、[JavaScript Stack from Scratch](https://github.com/verekia/js-stack-from-scratch)を翻訳し、まとめて読めるように1ファイルにしたものです。元の翻訳と各種ファイルについては、[日本語訳forkリポジトリ](https://github.com/takahashim/js-stack-from-scratch)を参照してください。また、原文が活発に更新されているため、訳文も追従して更新されます。ご了承ください。）

# ゼロから始めるJavaScript生活

[![Yarn](https://qiita-image-store.s3.amazonaws.com/0/4293/2ee7be54-48f2-818a-8c81-4fc9d328b138.png)](https://yarnpkg.com/)[![React](https://qiita-image-store.s3.amazonaws.com/0/4293/23b5076b-0756-7e63-11f4-ca08cd5163e2.png)](https://facebook.github.io/react/)[![Gulp](https://qiita-image-store.s3.amazonaws.com/0/4293/12e41319-0fc3-36e6-14d9-e5f42d8b1e17.png)](http://gulpjs.com/)[![Redux](https://qiita-image-store.s3.amazonaws.com/0/4293/059d0798-395c-6b46-1853-02f515a9592e.png)](http://redux.js.org/)[![ESLint](https://qiita-image-store.s3.amazonaws.com/0/4293/ebf4eabb-78c8-0e85-6a27-fab4e5833da0.png)](http://eslint.org/)[![Webpack](https://qiita-image-store.s3.amazonaws.com/0/4293/dca06b8b-ca2b-e174-a08c-f325834f762d.png)](https://webpack.github.io/)[![Mocha](https://qiita-image-store.s3.amazonaws.com/0/4293/4182051d-cca7-f314-ffdb-58b243aa933c.png)](https://mochajs.org/)[![Chai](https://qiita-image-store.s3.amazonaws.com/0/4293/09ee8c5d-4472-3231-5440-0fc078353b5d.png)](http://chaijs.com/)[![Flow](https://qiita-image-store.s3.amazonaws.com/0/4293/02965c17-7816-dd23-e604-3c608e0c2c3b.png)](https://flowtype.org/)

モダンJavaScriptスタックチュートリアル、**ゼロから始めるJavaScript生活**へようこそ。

> ⚠️️ このチュートリアルのメジャーアップデート版を3月初旬に公開する予定です。ご期待下さい! [より詳しく(英語)](https://github.com/verekia/js-stack-from-scratch/issues/133).

これはJavaScriptスタックを使い始めるための最短最速のガイドです。このガイドは一般的なプログラミングの知識とJavaScriptの基礎を前提としています。**これら全てのツールを一緒につなぎ合わせることにフォーカスしており**、各ツールについて**可能な限りシンプルな例**を提供します。このチュートリアルは、**独自のボイラープレートをゼロから準備するための方法**として見ることもできます。

もちろん、ちょっとしたJSによるインタラクションを含むだけのシンプルなウェブページを作るのであれば、ここで紹介するスタックを全て使う必要はありません(ES6コードを複数のファイルに書いてCLIでコンパイルしたいのであれば、Browserify/Webpack + Babel + jQueryの組み合わせで十分です)。しかし、スケールするウェブアプリを構築するにあたってセットアップの手助けが必要であれば、このチュートリアルが重宝するでしょう。

このチュートリアルの目標はさまざまなツールを組み立てることにあるため、これらのツールの仕組みについて、それぞれの詳細については触れません。それらのより深い知識を習得したい場合、それぞれのドキュメントを参照するか、他のチュートリアルを探してください。

このチュートリアルで説明しているスタックはその大部分にReactを使用しています。もし初心者の方がReactについてのみ学びたいのであれば、[create-react-app](https://github.com/facebookincubator/create-react-app)で設定済みのReact環境をすぐに試すことができます。例えばすでにReactを使っているチームに加わり、学習用playgroundでキャッチアップするということであれば、このようなアプローチをお勧めします。このチュートリアルでは、内部で何が行っているかをすべて理解してもらえるよう、既存の設定を使わないようにしています。

コード例は章ごとに利用できます。それぞれ`yarn && yarn start`または`npm install && npm start`で実行できます。各章の**ステップバイステップの指示**に従って全てゼロから入力することを推奨します。

**すべての章には、それまでの章のコードが含まれています** 。そのため、全てを含んだプロジェクトのボイラープレートを探しているのであれば、最終章をcloneすればそれで使えます。

注意: 章の順序は必ずしも最も教育的なものではありません。たとえば、テスティング/型検査はReactを導入する前に行うこともできます。しかしながら、章を移動させたり以前の章を修正するのは、以降の章を全て変更する必要があるため、かなり困難です。いったん状況が落ち着いてから、より良い方法のために配置を変更するかもしれません。

このチュートリアルのコードはLinux、macOS、Windows上で動作します。

## 目次

[1 - Node、NPM、Yarn、そして package.json](#1---nodenpmyarnそしてpackagejson)
[2 - packageのインストールと使用](#2---パッケージのインストールと利用)
[3 - Babel と Gulp による ES6 のセットアップ](#3---babelとgulpによるes6のセットアップ)
[4 - ES6のクラス構文を使う](#4---es6のクラス構文を使う)
[5 - ES6モジュール構文](#5---es6モジュール構文)
[6 - ESLint](#6---eslint)
[7 - Webpackによるクライアントアプリ](#7---webpackによるクライアントアプリ)
[8 - React](#8---react)
[9 - Redux](#9---redux)
[10 - Immutable JS と Redux の改良](#10---immutable-jsとreduxの改良)
[11 - Mocha、Chai、Sinonによるテスティング](#11---mochachaisinonによるテスティング)
[12 - Flowによる型検査](#12---flow)

## 今後の予定

本番/開発環境, Express, React Router, サーバサイドレンダリング, Styling, Enzyme, Gitフック。

## Credits

Created by [@verekia](https://twitter.com/verekia) – [verekia.com](http://verekia.com/).

License: MIT


# 1 - Node、NPM、Yarn、そしてpackage.json

この章ではNode、NPM、Yarn、そして基本的な`package.json`ファイルのセットアップを行います.

まず、バックエンドのJavaScriptとして使われるだけではなく、モダンなフロントエンドスタックを構築するためのツールとしても使われる、Nodeをインストールする必要があります。

macOSとWindowsバイナリ用[ダウンロードページ](https://nodejs.org/en/download/current/)に行くか、Linuxディストリビューション用の[package manager installations page](https://nodejs.org/en/download/package-manager/)に行きます。

たとえば、**UbuntuかDebian** であれば、Nodeをインストールするために以下のコマンドを実行します。

```bash
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs
```

Node のバージョンは6.5.0以降であればどれでも構いません。

Nodeの標準パッケージマネージャー、`npm`はNodeに付属しているため、別途インストールする必要はありません。

**注意**: Nodeがすでにインストールされている場合、`nvm`([Node Version Manager](https://github.com/creationix/nvm)) をインストールし、`nvm`を使って最新のNodeをインストールしてください。

[Yarn](https://yarnpkg.com/)はNPMよりも高速なもう一つのパッケージマネージャで、オフライン環境にも対応し、依存しているものを[より期待通りに](https://yarnpkg.com/en/docs/yarn-lock)取得します。Yarnは2016年10月に[リリース](https://code.facebook.com/posts/1840075619545360)されて以来、パッケージマネージャの新たな選択肢としてJavaScriptコミュニティに急速に受け入れられつつあります。このチュートリアルではYarnを使っています。NPMを使いたい場合は、`yarn add`や`yarn add --dev`などのコマンドを、`npm install --save`や`npm install --save-dev`などと読み替えてください。

- [インストール手順](https://yarnpkg.com/en/docs/install)に従ってYarnをインストールします。`npm install -g yarn`や`sudo npm install -g yarn`などでインストールすることもできます（そうです、YarnをインストールするのにNPMを使うのです。Internet ExplorerやSafariを使ってChromeをインストールするようなものですね!）

- 新しい作業用フォルダを作り、`cd`で移動します。
- `yarn init`を実行し、質問に答えると(`yarn init -y`で全ての質問をスキップできます)、`package.json`ファイルが自動生成されます。
- `console.log('Hello world')`と書かれた`index.js`ファイルを作ります。
- そのフォルダ内で`node .`と実行します(`index.js`はNodeがカレントフォルダ内で探すデフォルトのファイル名です)。"Hello world"と表示されるはずです。

`node .`でプログラムを実行させるのはやや低レベル寄りです。代わりにNPM/Yarnスクリプトを使ってコードを実行します。より複雑なプログラムを実行する場合でも、必ず`yarn start`で実行できるようにするのは、適切な抽象化になっています。

- `package.json`内の`scripts`オブジェクトに`"start": "node ."`と追加します。

```json
"scripts": {
  "start": "node ."
}
```

`package.json`は構文的に正しいJSONファイルでなければならないので、末尾のカンマを追加してはいけません。`package.json`ファイルを手で編集する時はよく注意してください。

- `yarn start`と実行します。`Hello world`と表示されるはずです。

- `.gitignore`を作り、以下の内容を追加します。

```gitignore
npm-debug.log
yarn-error.log
```

**注意**: 私が作った`package.json`ファイル内には、各章に対して`tutorial-test`スクリプトがあります。このスクリプトは`yarn && yarn start`で各章が正しく実行されることを私自身がテストするためのものです。他のプロジェクトに使う場合は、ここは削除しても構いません。

(原文: [1 - Node, NPM, Yarn, and package.json](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/1-node-npm-yarn-package-json))


# 2 - パッケージのインストールと利用

この章では、パッケージをインストールして使ってみます。「パッケージ」とは他の誰かが書いたコードの集まりのことで、これから書くコード内で利用することができます。どんなコードでもです。ここでは、例として色を扱うためのパッケージを使ってみます。

- コミュニティ製のパッケージ`color`をインストールするため、`yarn add color`と実行します。

`package.json`を開くと、Yarnが`dependencies`に`color`を自動的に追加したのがわかります。

そして`node_modules`フォルダが作られ、そこにパッケージが保存されます。

- `.gitignore`ファイルに`node_modules/`を追加します(まだ`git init`を実行していなければここで実行します)。

`yarn.lock`というファイルをYarnが生成したことにも気づくでしょう。このファイルはリポジトリにコミットしておくべきです。こうしておけば、チーム内のメンバー全員が同じバージョンのパッケージを利用するようになります。もしYarnではなくNPMを使いたい場合は、*shrinkwrap*がこのファイルの代わりとなります。

- `index.js`ファイルに`const Color = require('color');`と追加します。
- 例として以下のような形でパッケージを使ってみます: `const redHexa = Color({r: 255, g: 0, b: 0}).hex();`
- `console.log(redHexa)`を追加します。
- `yarn start`と実行すると、`#FF0000`と表示されるはずです。

おめでとうございます、パッケージをインストールして使うことができました!

`color`はこの章の中でしか使わない、パッケージの使い方を説明するためだけのシンプルなパッケージです。もう不要になったので、アンインストールして構いません。

- `yarn remove color`を実行します

**注意**: パッケージの依存関係には、`"dependencies"`と`"devDependencies"`の2種類あります。`"dependencies"`は`"devDependencies"`より一般的なもので、後者は開発している間だけ使うパッケージであり、本番環境では使いません（典型的には、ビルド関係のパッケージや、linterなどがあります）。`"devDependencies"`に追加するには、`yarn add --dev [package]`と実行します。

(原文: [2 - Installing and using a package](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/2-packages))


# 3 - BabelとGulpによるES6のセットアップ

ES6構文を使ってみましょう。ES6構文は「古い」ES5構文を大幅に改善したものです。全てのブラウザとJS環境はES5を理解しますが、ES6は理解するとは限りません。そのため、Babelと呼ばれる、ES6ファイルをES5ファイルに変換するツールを使います。Babelを実行するには、タスクランナーのGulpを使います。`package.json`ファイルの`scripts`以下に書くタスクに似ていますが、タスクをJSファイルに書く方がJSONファイルに書くよりもシンプルで汚くなりにくいです。そのため、Gulpと、Gulp用のBabelプラグインもインストールしておきましょう:

- `yarn add --dev gulp`と実行します
- `yarn add --dev gulp-babel`と実行します
- `yarn add --dev babel-preset-latest`と実行します
- `yarn add --dev del`と実行します (これは後述の通り、`clean`タスクのためです)
- `package.json`ファイルに、Babelの設定のための`babel`フィールドを追加します。最新のBabelプリセットを使うため、以下のようにします:

```json
"babel": {
  "presets": [
    "latest"
  ]
},
```

**注意**: `.babelrc`ファイルがプロジェクトのルートにあると、`package.json`の`babel`よりもそちらが優先されます。ルートフォルダはそのうちどんどん膨れ上がっていくため、`package.json`が巨大にならないうちは、Babelの設定は`package.json`内に記述するようにします。

- `index.js`ファイルを新たな`src`フォルダに移動します。これはES6のコードを記述するためのフォルダです。`lib`フォルダはコンパイル後のES5コードが置かれます。GulpとBabelはこのコード生成の面倒を見ます。`index.js`にある前章の`color`関連のコードを削除し、以下の簡単な内容に書き換えます:

```javascript
const str = 'ES6';
console.log(`Hello ${str}`);
```

ここでは*テンプレート文字列リテラル*を使っています。これはES6の新しい構文で、`${}`を使った文字列連結なしで変数を直接文字列内に埋め込むためのものです。テンプレート文字列リテラルは**バッククォート**を使っていることに注意してください。

- 以下の内容で`gulpfile.js`を作ります:

```javascript
const gulp = require('gulp');
const babel = require('gulp-babel');
const del = require('del');
const exec = require('child_process').exec;

const paths = {
  allSrcJs: 'src/**/*.js',
  libDir: 'lib',
};

gulp.task('clean', () => {
  return del(paths.libDir);
});

gulp.task('build', ['clean'], () => {
  return gulp.src(paths.allSrcJs)
    .pipe(babel())
    .pipe(gulp.dest(paths.libDir));
});

gulp.task('main', ['build'], (callback) => {
  exec(`node ${paths.libDir}`, (error, stdout) => {
    console.log(stdout);
    return callback(error);
  });
});

gulp.task('watch', () => {
  gulp.watch(paths.allSrcJs, ['main']);
});

gulp.task('default', ['watch', 'main']);

```

全体を理解するために少し時間をとりましょう。

GulpのAPI自体は非常に率直なものです。`gulp.task`を定義し、その中では`gulp.src`でファイルを参照し、そのファイルに対し一連の操作を`.pipe()`を使って適用し(この例の`babel()`のように)、新しいファイルを`gulp.dest`に出力します。Gulpのタスクは、`gulp.task`の第2引数として(`['build']`のような)配列の形で渡された必要なタスクを先に実行することができます。より完全な紹介は、[ドキュメント](https://github.com/gulpjs/gulp)を参照してください。

まず最初に`paths`オブジェクトを定義します。これは異なるファイルパスを格納し、DRYに保つためです。

続いて5つのタスク: `build`、`clean`、`main`、`watch`、そして`default`を定義します。

- `build`は`src`以下のソースファイルを変換し`lib`に保存するため、Babelが呼ばれるところです。
- `clean` は`build`を行う前に、`lib`フォルダに自動生成されるファイル全てを削除するタスクです。このタスクは、`src`内のファイルをリネームや削除したり、ビルドに失敗したことに気づかない場合でも`lib`フォルダを`src`フォルダに確実に同期させるため、生成されたファイルを削除するのに便利です。Gulpストリームと連携してファイルを削除するために、ここでは`del`パッケージを使っています(これはGulpでのファイルの削除方法として[推奨](https://github.com/gulpjs/gulp/blob/master/docs/recipes/delete-files-folder.md)されている方法です)。
- `main`は前章で`node .`と入力し実行させているのとほぼ同じもので、`lib/index.js`を実行することだけが異なっています。`index.js`はNodeが探しにいく標準のファイル名なので、単に`node lib`とだけ書いています(DRYを守るために`libDir`変数を使っています)。タスク内の`require('child_process').exec`と`exec`の部分はシェルコマンドを実行するNodeの標準関数です。`stdout`は`console.log()`に渡し、`gulp.task`のコールバック関数を使って潜在的なerrorを返します。この部分がはっきりと理解できなくても気にする必要はありません。このタスクは基本的に`node lib`を実行するためのものであるとだけ覚えてください。
- `watch` は特定のファイルに更新があった場合に`main`タスクを実行します。
- `default` は、コマンドラインで単に`gulp`と実行した場合に呼び出される特殊なタスクです。

**注意**: どうしてGulpファイル内でES6コードが使えるのか、気になっているかもしれません。なぜならこのコードはBabelでES5コードにトランスパイルされないからです。その理由は、ここではES6を標準でサポートしているバージョンのNodeを使っているためです(`node -v`を実行し、バージョン6.5.0以上のNodeを使っていることを確認してください)。

さあ、動かしてみましょう!

- `package.json`内の`start`スクリプトを`"start": "gulp"`に変更します。
- `yarn start`と実行します。"Hello ES6"と表示され、変更の監視が始まるはずです。 `src/index.js`に間違ったコードを書いてみて、saveしたときにGulpが自動的にエラーを表示するか試してみましょう。
- `/lib/`を`.gitignore`に追加します。

(原文: [3 - Setting up ES6 with Babel and Gulp](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/3-es6-babel-gulp))


# 4 - ES6のクラス構文を使う

- 新しいファイル`src/dog.js`を作り、以下のES6クラスを書きます:

```javascript
class Dog {
  constructor(name) {
    this.name = name;
  }

  bark() {
    return `Wah wah, I am ${this.name}`;
  }
}

module.exports = Dog;
```

以前から他の言語でOOPをしたことがあるなら、特に意外な点はないでしょう。しかし、JavaScriptにクラス構文が取り入れられたのはつい最近なのです。このクラスは`module.exports`へ代入することにより、外の世界にさらされます。

典型的なES6コードはクラスや`const`、`let`、 `bark()`で使われているような(backtickによる)"テンプレート文字列"、アロー関数(`(param) => { console.log('Hi'); }`)などが使われます。この例では使われていないものもありますが。

`src/index.js`ファイルに、以下のように書きます:

```javascript
const Dog = require('./dog');

const toby = new Dog('Toby');

console.log(toby.bark());
```

このように、先ほど使ったコミュニティ製の`color`パッケージとは異なり、自分で作ったファイルをrequireするときには、`require()`内で`./`を使います。

- `yarn start`を実行します。'Wah wah, I am Toby'と表示されるはずです。

- `lib`に生成されたコードを見て、コンパイルされたコードがどのようになっているかを確認します(例えば`const`の代わりに`var`があるなど).

(原文: [4 - Using the ES6 syntax with a class](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/4-es6-syntax-class))


# 5 - ES6モジュール構文

ここでは、`const Dog = require('./dog')`を`import Dog from './dog'`に置き換えます。これは("CommonJS"のモジュール構文と比べると)より新しいES6モジュールの構文です。

`dog.js`内の`module.exports = Dog`を`export default Dog`に置き換えます。

`dog.js`では、`Dog`の名前は`export`の中でしか使われていないことに注意してください。そのため、次の例のように、匿名のクラスを直接エクスポートすることも可能です:

```javascript
export default class {
  constructor(name) {
    this.name = name;
  }

  bark() {
    return `Wah wah, I am ${this.name}`;
  }
}
```

`index.js`ファイルの`import`での'Dog'という名前は実際には使う人次第だと思われたかもしれません。実際、このように書いても問題なく動きます。

```javascript
import Cat from './dog';

const toby = new Cat('Toby');
```

もちろん、インポートしたclass / moduleの名前をそのまま使うことがほとんどです。そうしない例としては、Gulpファイル内で`const babel = require('gulp-babel')`とする場合が挙げられます。

では、`gulpfile.js`ファイル内の`require()`はどうでしょうか？ 代わりに`import`が使えるでしょうか？ 最新版のNodeはES6のほとんどの機能に対応していますが、ES6モジュールにはまだ対応していません。ありがたいことに、GulpはBabelに手助けをしてもらえます。`gulpfile.js`を`gulpfile.babel.js`にリネームすれば、Babelは`import`されたモジュールをGulpに渡す役割を担ってくれます。

- `gulpfile.js`を`gulpfile.babel.js`にリネームします。

- `require()`を以下のように書き換えます:

```javascript
import gulp from 'gulp';
import babel from 'gulp-babel';
import del from 'del';
import { exec } from 'child_process';
```

`child_process`から`exec`が直接展開されるシンタックスシュガーに注意してください。実に美しいです!

- `yarn start`を実行すると "Wah wah, I am Toby" と表示されるはずです。

(原文: [5 - The ES6 modules syntax](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/5-es6-modules-syntax))


# 6 - ESLint

潜在的な問題を見つけるため、コードをlintしましょう。ESLintはES6コード用のlinterです。ルールを自身で細かく設定する代わりに、Airbnbが作った設定を利用します。この設定はプラグインをいくつか使うため、プラグインをインストールする必要があります。

- `yarn add --dev eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react`を実行します

このように、複数のパッケージを一つのコマンドでインストールできます。いつものように、これらは全て`package.jsonに追加されます。

`package.json`に以下のような`eslintConfig`フィールドを追加します:

```json
"eslintConfig": {
  "extends": "airbnb",
  "plugins": [
    "import"
  ]
},
```

`plugins`の部分はES6のimport構文を使うことをESLintに教えています。

**注意**: プロジェクトのルートにある`.eslintrc.js`や`.eslintrc.json`、`.eslintrc.yaml`ファイルの代わりに、`package.json`ファイルの`eslintConfig`フィールドを使うこともできます。Babelの設定と同様、ルートフォルダが多くのファイルで溢れるのを避けるためこのようにしていますが、ESLintの設定が複雑化してきたら、この代替策を検討してください。

ESLintを実行するためのGulpタスクが必要です。そのため、ESLint Gulpプラグインをインストールします。

- `yarn add --dev gulp-eslint`を実行します

次のようなタスクを`gulpfile.babel.js`に追加します:

```javascript
import eslint from 'gulp-eslint';

const paths = {
  allSrcJs: 'src/**/*.js',
  gulpFile: 'gulpfile.babel.js',
  libDir: 'lib',
};

// [...]

gulp.task('lint', () => {
  return gulp.src([
    paths.allSrcJs,
    paths.gulpFile,
  ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});
```

Gulpにこのタスクを伝えるため、`gulpfile.babel.js`と、`src`以下にあるJSファイルをインクルードする必要があります。

以下のように、Gulpタスク`build`の前提条件に`lint`タスクを追加します:

```javascript
gulp.task('build', ['lint', 'clean'], () => {
  // ...
});
```

- `yarn start`を実行すると、Gulpfile内のたくさんのlintのエラーと、`index.js`内で`console.log()`を使っている警告が表示されるはずです。

警告の一種として、`'gulp' should be listed in the project's dependencies, not devDependencies (import/no-extraneous-dependencies)`といった出力があるとか思います。これは実際には誤検知に当たります。ESLintはビルド時のみに使われるJSファイルがどれで、そうではないJSファイルがどれかを知ることができません。そのため、コード内のコメントを使ってESLintに教えてあげる必要があります。`gulpfile.babel.js`ファイルの先頭に、以下を追加します:

```javascript
/* eslint-disable import/no-extraneous-dependencies */
```

こうすることで、ESLintはこのファイルに`import/no-extraneous-dependencies`ルールを適用しなくなります。

残る問題は`Unexpected block statement surrounding arrow body (arrow-body-style)`です. これは貴重な指摘です。ESLintは以下のようなコードのもっと良い書き方を教えてくれているのです。

```javascript
() => {
  return 1;
}
```

これは次のように修正するべきです:

```javascript
() => 1
```

関数がreturn文しか含まない場合、ブレースとreturn文とセミコロンを省略できるためです。

それではGulpファイルを正しく修正してみましょう:

```javascript
gulp.task('lint', () =>
  gulp.src([
    paths.allSrcJs,
    paths.gulpFile,
  ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError())
);

gulp.task('clean', () => del(paths.libDir));

gulp.task('build', ['lint', 'clean'], () =>
  gulp.src(paths.allSrcJs)
    .pipe(babel())
    .pipe(gulp.dest(paths.libDir))
);
```

最後の問題は`console.log()`についてのものです。この例で問題の元となっている`index.js`内での`console.log()`は正しいものであることを伝えましょう。ご想像の通り、`/* eslint-disable no-console */`を`index.js`の先頭に置きます。

- `yarn start`を実行すると、すべて解決されている状態に戻ります。

**注意**: この章ではコンソール用にESLintを設定しています。ビルド時/pushする前にエラーを見つけられるのは素晴らしいことですが、もしかするとIDEにも統合したくなるかもしれません。しかし、IDEに付属しているES6用のlintツールを使わないでください。そのツールがlinting用に使っているバイナリは`node_modules`フォルダにあるように設定してください。そううするとそのツールはプロジェクトの全ての設定、Airbnbのプリセットなど全てが利用できるようになります。そうでなければ、一般的なES6のlintingしか使えるようになりません。

(原文: [6 - ESLint](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/6-eslint))


# 7 - Webpackによるクライアントアプリ

## アプリの構造

- プロジェクトのルートに`dist`フォルダを作り、以下の`index.html`ファイルを追加します:

```html
<!doctype html>
<html>
  <head>
  </head>
  <body>
    <div class="app"></div>
    <script src="client-bundle.js"></script>
  </body>
</html>
```

`src`フォルダには、次のサブフォルダを作ります: `server`、`shared`、`client`。そしてカレントにある`index.js`を`server`フォルダに、`dog.js`を`shared`フォルダに移動します。`client`フォルダには`app.js`ファイルを作ります。

Nodeバックエンドは使わないのですが、この分割はそれぞれの所属をはっきりさせるのに役立ちます。`server/index.js`内の`import Dog from './dog';`を`import Dog from '../shared/dog';`に変更する必要があり、そうしなければESLintは解決できないモジュールのエラーを検出してくれます。

`client/app.js`ファイルに以下を書きます:

```javascript
import Dog from '../shared/dog';

const browserToby = new Dog('Browser Toby');

document.querySelector('.app').innerText = browserToby.bark();
```

`package.json`の`eslintConfig`に以下を追加します:

```json
"env": {
  "browser": true
}
```

こうすると、`window`や`document`といったブラウザでは必ずアクセスできる変数を使っていても、ESLintは未定義変数の警告を出さないようになります。

さらに、`Promise`など、最新のESの仕様を使いたい場合には、[Babel Polyfill](https://babeljs.io/docs/usage/polyfill/)をクライアントコードに含める必要があります。

- `yarn add babel-polyfill`を実行します

そして`app.js`の先頭に、次のようなimportを追加します:

```javascript
import 'babel-polyfill';
```

このpolyfillを使うと、バンドルのサイズが増えるため、これらの機能を使いたい場合のみ追加するようにします。このチュートリアルでは無駄のないボイラープレートのコードを提供するために、このpolyfillを導入し、次章以降のコードサンプルで使っていきます。

## Webpack

Node環境では、いろんなファイルを自由に`import`しても、Nodeはファイルシステムを使って適切に解決してくれました。一方ブラウザでは、ファイルシステムがないため、`import`もファイルを参照することができません。エントリポイントのファイルである`app.js`が必要なインポートのツリー構造を探してこれるよう、依存関係のツリー全体を1つのファイルに「バンドル」しなければなりません。このためのツールがWebpackです。

WebpackはGulp同様、`webpack.config.js`という設定ファイルを使用します。GulpはBabelを利用してES6のimportとexportを使えるようにしていましたが、Webpackも同様のことができます。そのためには、`webpack.config.babel.js`という名前のファイルを使います。

- 空のファイル`webpack.config.babel.js`を作ります

- Gulpの`link`タスクに`webpack.config.babel.js`を、`paths`定数にいくつかパスを追加します。

```javascript
const paths = {
  allSrcJs: 'src/**/*.js',
  gulpFile: 'gulpfile.babel.js',
  webpackFile: 'webpack.config.babel.js',
  libDir: 'lib',
  distDir: 'dist',
};

// [...]

gulp.task('lint', () =>
  gulp.src([
    paths.allSrcJs,
    paths.gulpFile,
    paths.webpackFile,
  ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError())
);
```

WebpackにBabelを使ってES6ファイルを扱う方法を教える必要があります(GulpにES6ファイルの扱いを教えるために`gulp-babel`を使ったのと同様です)。Webpackでは、古い素のJavaScriptではないものを扱う場合、*loaders*を使います。Webpack用のBabel loaderをインストールしてみましょう。

- `yarn add --dev babel-loader`を実行します

- `webpack.config.babel.js`ファイルに以下を書きます:

```javascript
export default {
  output: {
    filename: 'client-bundle.js',
  },
  devtool: 'source-map',
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: [/node_modules/],
      },
    ],
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
  },
};
```

これを解読してみましょう:

このファイルはWebpackが読めるように`export`する必要があります。`output.filename`が生成したいバンドルのファイル名です。`devtool: 'source-map'`はブラウザでのデバッグが捗るようにするためのソースマップを有効にします。`module.loaders`には`test`があります。これは`babel-loader`がどんなファイルを扱うかテストするかを正規表現で指定しています。次章では`.js`ファイルと(React用の)`.jsx`ファイルの両方を扱うため、`/\.jsx?$/`という正規表現を使っています。`node_modules`フォルダはトランスパイルを行わないため、excludeで排除しています。`resolve`の部分では、拡張子なしで`import`した場合、どのような種類のファイルを`import`するべきかをWebpackに指定しています。これは例えば`import Foo from './foo'`と書くと、`foo`のところは`foo.js`や`foo.jsx`と解釈されるようにするためのものです。

さて、Webpackの設定は終わりましたが、*実行*するにはもうちょっとかかります。

## WebpackをGulpに統合する

Webpackはさまざまなことを行います。プロジェクトがクライアントサイドのものであれば、Gulpをすっかり置き換えてしまうこともできます。一方で、Gulpはもっと汎用的なツールで、linting、テスト、バックエンドタスクなどに向いています。初学者の人にとっては、Webpackの複雑な設定よりもシンプルで理解しやすいでしょう。ここではすでにGulpのセットアップとワークフローを構築済みなので、WebpackをGulpのビルドに統合させるのが理想的でしょう。

それではWebpackを実行するGulpタスクを作りましょう。`gulpfile.babel.js`を開きます。

`node lib/`を実行する`main`タスクはもう必要ありません。`index.html`を開けばアプリが実行されるためです。

- `import { exec } from 'child_process'`を削除します

Gulpプラグイン同様、`webpack-stream`パッケージを使えば、GulpにWebpackに統合するのも簡単です。

- `yarn add --dev webpack-stream`を実行し、パッケージをインストールします

- 以下の`import`を追加します:

```javascript
import webpack from 'webpack-stream';
import webpackConfig from './webpack.config.babel';
```

2行目で設定ファイルを取り込んでいます。

先ほど説明したとおり、次章では`.jsx`ファイルを使います(まず使うのはクライアント側でですが、サーバ側でも後ほど使用します)。ちょっと早いですがさっそく設定しておきましょう。

- constの定数宣言を次のようにします:

```javascript
const paths = {
  allSrcJs: 'src/**/*.js?(x)',
  serverSrcJs: 'src/server/**/*.js?(x)',
  sharedSrcJs: 'src/shared/**/*.js?(x)',
  clientEntryPoint: 'src/client/app.js',
  gulpFile: 'gulpfile.babel.js',
  webpackFile: 'webpack.config.babel.js',
  libDir: 'lib',
  distDir: 'dist',
};
```

`.js?(x)`は`.js`ファイルと`.jsx`ファイルにマッチするパターンです。

アプリケーションの別々に分けられた部分についてと、エントリポイントのファイルが定数に追加されました。

- `main`を次のように変更します:

```javascript
gulp.task('main', ['lint', 'clean'], () =>
  gulp.src(paths.clientEntryPoint)
    .pipe(webpack(webpackConfig))
    .pipe(gulp.dest(paths.distDir))
);
```

**注意**: `build`タスクは現状、`src`以下にある全ての`.js`ファイルをES6からES5にトランスパイルします。ここではコードを`server`と`shared`、`client`に分割しています。これは`server`と`shared`のみこのタスクでコンパイルするためのものです(`client`はWebpackが面倒を見るためです)。しかしながら、テスティングの章では、Webpackの外でテストするため`client`のコードもGulpでコンパイルする必要があります。そのため、その章にたどり着くまで、不要な重複ビルドが行われることになりますが、今のところはこれでも良いと同意してもらえると思います。実際には、今ここで扱うのはクライアントバンドルのみなので、`build`タスクも`lib`フォルダもその章までは特に使う必要がないものです。

- `yarn start`を実行すると、Webpackが`client-bundle.js`ファイルを作ります。`index.html`をブラウザで開くと"Wah wah, I am Browser Toby"と表示されるはずです。

最後に: `lib`フォルダとは異なり、`dist/client-bundle.js`ファイルと`dist/client-bundle.js.map`ファイルはビルドの度に`clean`タスクで消されません。

- `clientBundle: 'dist/client-bundle.js?(.map)'`を`paths`の設定に追加し、`clean`タスクを以下のように変更します:

```javascript
gulp.task('clean', () => del([
  paths.libDir,
  paths.clientBundle,
]));
```

- `/dist/client-bundle.js*`を`.gitignore`ファイルに追加します。

(原文: [7 - Client App with Webpack](https://github.com/verekia/js-stack-from-scratch/blob/master/tutorial/7-client-webpack))


# 8 - React

アプリの描画にReactを使ってみましょう。

まず、ReactとReactDOMをインストールします:

- `yarn add react react-dom`を実行します

この2つのパッケージは`"devDependencies"`ではなく`"dependencies"`に追加されます。ビルドツールと異なり、クライアントバンドルは本番環境用に使われるためです。

`src/client/app.js`を`src/client/app.jsx`にリネームし、ReactとJSXのコードを書いてみましょう:

```javascript
import 'babel-polyfill';

import React, { PropTypes } from 'react';
import ReactDOM from 'react-dom';
import Dog from '../shared/dog';

const dogBark = new Dog('Browser Toby').bark();

const App = props => (
  <div>
    The dog says: {props.message}
  </div>
);

App.propTypes = {
  message: PropTypes.string.isRequired,
};

ReactDOM.render(<App message={dogBark} />, document.querySelector('.app'));
```

**注意**: もしReactとそのPropTypesをよく知らないのであれば、まずReactについて学習してからこのチュートリアルに戻ってきてください。後の章ではReactが多用されるため、よく理解しておく必要があります。

Gulpfile内の`clientEntryPoint`の値に`.jsx`拡張子を追加します:

```javascript
clientEntryPoint: 'src/client/app.jsx',
```

ここではJSXの構文を使うため、BabelにJSXを変換するよう伝える必要があります。BabelにJSX構文の処理方法を教えるReact用のBabelプリセットをインストールします: `yarn add --dev babel-preset-react` そして`package.json`ファイルの`babel`エントリを次のように変更します:

```json
"babel": {
  "presets": [
    "latest",
    "react"
  ]
},
```

これで`yarn start`実行後、`index.html`を開くと、Reactが"The dog says: Wah wah, I am Browser Toby"と出力するのを確認できるはずです。

(原文: [8 - React](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/8-react))


# 9 - Redux

本章では(おそらくここまでで最も難しい章なのですが)、アプリケーションに[Redux](http://redux.js.org/)を追加し、Reactと連携させます。Reduxはアプリケーションの状態を管理するもので、アプリの状態を表現する素のJavaScriptオブジェクトである**store**、一般的にユーザが起点となる**action**、アクションハンドラにも見える**reducer**が合わさったものです。reducerはアプリケーションの状態(*store*)に影響を及ぼし、アプリケーションの状態が変更がされると、アプリケーションに何かが起こります。Reduxの分かりやすい動くデモが[ここ](http://slides.com/jenyaterpil/redux-from-twitter-hype-to-production#/9)にあります。

Reduxを可能な限りシンプルに扱うにはどうすればよいか説明するため、アプリはメッセージとボタンで構成されるようにします。メッセージは犬が鳴いているかどうか(最初は鳴いていません)を伝え、ボタンを押すと犬が鳴き、メッセージが更新されるようにします。

ここでは、`redux`と`react-redux`の2つのパッケージが必要になります。

- `yarn add redux react-redux`を実行します。

はじめに、2つのフォルダ、`src/client/actions`と`src/client/reducers`を作ります。

- `actions`内に、以下の`dog-actions.js`ファイルを作ります:

```javascript
export const MAKE_BARK = 'MAKE_BARK';

export const makeBark = () => ({
  type: MAKE_BARK,
  payload: true,
});
```

ここではアクションタイプ`MAKE_BARK`を定義しています。また、`MAKE_BARK`アクションのトリガーとなる関数(これは*action creator*とも言います)`makeBark`も定義します。どちらも他のファイルから利用するため、exportされています。このアクションは[Flux Standard Action](https://github.com/acdlite/flux-standard-action)モデルで実装されています。`type`属性と`payload`属性を持っているのはそのためです。

- `reducers`フォルダに以下のような`dog-reducer.js`ファイルを作ります:

```javascript
import { MAKE_BARK } from '../actions/dog-actions';

const initialState = {
  hasBarked: false,
};

const dogReducer = (state = initialState, action) => {
  switch (action.type) {
    case MAKE_BARK:
      return { hasBarked: action.payload };
    default:
      return state;
  }
};

export default dogReducer;
```

ここではアプリの初期状態として、`hasBarked`プロパティが`false`になっている状態を定義しています。また、どのアクションが実行されたかによって状態を作る関数`dogReducer`も定義しています。この関数は状態を変更することがありません。代わりに新しい状態オブジェクトを返します。

- *store*を作るため`app.jsx`を修正します。ファイルの中身全体を以下の内容に置き換えます:

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import dogReducer from './reducers/dog-reducer';
import BarkMessage from './containers/bark-message';
import BarkButton from './containers/bark-button';

const store = createStore(combineReducers({
  dog: dogReducer,
}));

ReactDOM.render(
  <Provider store={store}>
    <div>
      <BarkMessage />
      <BarkButton />
    </div>
  </Provider>
  , document.querySelector('.app')
);
```

見ると明らかなように、Reduxの関数`createStore`がstoreを作ります。storeオブジェクトはReduxの`combineReducers`関数を使って、reducerを全て(この例では1つだけですが)集めたものです。各reducerはここで名前がつけられます。ここでは`dog`という名前をつけています。

ここは純粋なReduxの部分です。

それでは`react-redux`を使ってReduxとReactを結びつけましょう。`react-redux`がReactアプリにstoreを渡せるようにするため、アプリ全体を`<Provider>`コンポーネントで包みます。このコンポーネントは1つだけしか子要素を持てません。そのためここでは`<div>`要素を作り、この`<div>`要素にアプリの2つの重要な要素である`BarkMessage`と`BarkButton`を持たせるようにします。

`import`セクションにある通り、`BarkMessage`と`BarkButton`は`containers`フォルダからimportしたものです。ここは**Components** と **Containers**という２つのコンセプトを紹介するよい機会です。

*Component* は *賢くない(dumb)* Reactコンポーネントです。これはReduxの状態について何も知らないという意味です。*Containers* は *賢い(smart)*なコンポーネントです。これは状態を知っており、他の賢くないコンポーネントに*接続(connect)*できるためです。

- `src/client/components`と`src/client/containers`の2つのフォルダを作ります。

- `components`の中に、以下のファイルを作ります:

**button.jsx**

```javascript
import React, { PropTypes } from 'react';

const Button = ({ action, actionLabel }) => <button onClick={action}>{actionLabel}</button>;

Button.propTypes = {
  action: PropTypes.func.isRequired,
  actionLabel: PropTypes.string.isRequired,
};

export default Button;
```

そして、**message.jsx**:

```javascript
import React, { PropTypes } from 'react';

const Message = ({ message }) => <div>{message}</div>;

Message.propTypes = {
  message: PropTypes.string.isRequired,
};

export default Message;

```

これらは*賢くない*コンポーネントの例です。ロジックがなく、Reactの**props**経由で問い合わせが来たものをそのまま返すだけのものです。`button.jsx` と `message.jsx` の主な違いは、`Button`はそのプロパティとして**アクション(action)** を持っていることです。アクションは`onClick`イベントに結び付けられています。アプリのコンテキストで、`Button`ラベルは変化することがありませんが、`Message`コンポーネントはアプリの状態を反映し、状態によって変化します。

繰り返しますが、 *コンポーネント* はReduxの **アクション** やアプリの**状態** について何も知りません。そのため、適切な*actions* と *data*を2つの賢くないコンポーネントに伝えるための賢い**コンテナ**を作ることになるのです。

- `containers`内に、以下のファイルを作ります:

**bark-button.js**

```javascript
import { connect } from 'react-redux';
import Button from '../components/button';
import { makeBark } from '../actions/dog-actions';

const mapDispatchToProps = dispatch => ({
  action: () => { dispatch(makeBark()); },
  actionLabel: 'Bark',
});

export default connect(null, mapDispatchToProps)(Button);
```

そして **bark-message.js**:

```javascript
import { connect } from 'react-redux';
import Message from '../components/message';

const mapStateToProps = state => ({
  message: state.dog.hasBarked ? 'The dog barked' : 'The dog did not bark',
});

export default connect(mapStateToProps)(Message);
```

`BarkButton`は`Button`と`makeBark`アクション、そしてReduxの`dispatch`メソッドを結びつけます。また、`BarkMessage`はアプリケーションの状態と`Message`を結びつけます。状態が変更されると、`Message`は自動的に適切な`message`属性を再描画します。これらは`react-redux`の`connect`関数によって動作します。

- `yarn start`を実行し、`index.html`を開きます。そうすると、"The dog did not bark"とボタンが表示されます。ボタンをクリックすると、"The dog barked"というメッセージが表示されるはずです。

(原文: [9 - Redux](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/9-redux))


# 10 - Immutable JSとReduxの改良

## Immutable JS

前章とは違い、本章はとても簡単で、ちょっとした変更を行うだけです。

まず、コードベースに**Immutable JS**を追加します。Immutableはオブジェクトを変更(mutating)することなしに扱うためのライブラリです。例えば以下のようにする代わりに:

```javascript
const obj = { a: 1 };
obj.a = 2; // Mutates `obj`
```

こうすることができます:

```javascript
const obj = Immutable.Map({ a: 1 });
obj.set('a', 2); // Returns a new object without mutating `obj`
```

このアプローチは**関数型プログラミング**のパラダイムに則ったもので、Reduxとの相性がとても良くなっています。実際、reducer関数は引数として渡される状態を変更しない、純粋な関数でなければならず、状態オブジェクトを新しく作って返すようになっています。それではImmutableを使い、このやり方を強制してみましょう。

- `yarn add immutable`を実行します。

このコードベースでは`Map`を使うのですが、ESLintとAirbnbの設定はクラス以外に大文字の名前を使うと警告を出します。`package.json`の`eslintConfig`に以下を追加します:

```json
"rules": {
  "new-cap": [
    2,
    {
      "capIsNewExceptions": [
        "Map",
        "List"
      ]
    }
  ]
}
```

これは`Map`と`List`(この2つのImmutableなオブジェクトはずっと使うことになります)を例外扱いするようESLintルールを変更するものです。この冗長なJSONフォーマットはYarn/NPMによって自動的に行われるもので、残念ながらコンパクトにはできません。

それはさておき、Immutableに戻りましょう:

`dog-reducer.js`を以下のように修正します:

```javascript
import Immutable from 'immutable';
import { MAKE_BARK } from '../actions/dog-actions';

const initialState = Immutable.Map({
  hasBarked: false,
});

const dogReducer = (state = initialState, action) => {
  switch (action.type) {
    case MAKE_BARK:
      return state.set('hasBarked', action.payload);
    default:
      return state;
  }
};

export default dogReducer;
```

初期状態はImmutableのMapを使って作られます。そして新しい状態は、それ以前の状態を変更することのない`set()`を使って作られるようになります。

`containers/bark-message.js`の`mapStateToProps`関数を、`.hasBarked`の代わりに`.get('hasBarked')`を使うよう修正します:

```javascript
const mapStateToProps = state => ({
  message: state.dog.get('hasBarked') ? 'The dog barked' : 'The dog did not bark',
});
```

アプリケーションは以前と同様の振る舞いをするはずです。

**注意**: BabelがImmutableについて100KB制限を超えていると警告する場合, `package.json`の`babel`のところに`"compact": false`を追加します。

上記のコード片を見ると分かる通り、状態オブジェクトは素のオブジェクト属性`dog`を持っており、イミュータブルではありません。これはこれで構わないのですが、イミュータブルオブジェクトしか扱いたくない場合、Reduxの`combineReducers`関数を置き換えるため、`redux-immutable`パッケージをインストールできます。

**オプション**:

- `yarn add redux-immutable`を実行します。
- `app.jsx`にある`combineReducers`関数を`redux-immutable`からimportしたものに置き換えます。
- `bark-message.js`の`state.dog.get('hasBarked')`を`state.getIn(['dog', 'hasBarked'])`に置き換えます。

## Reduxアクション

アプリにアクションを加えていくにつれて、同じボイラープレートを何度も書き加えていくことになります。`redux-actions`パッケージを使えば、ボイラープレートのコードを減らしてくれます。`dog-actions.js`ファイルを`redux-actions`で簡潔に書き換えることができます。

```javascript
import { createAction } from 'redux-actions';

export const MAKE_BARK = 'MAKE_BARK';
export const makeBark = createAction(MAKE_BARK, () => true);
```

`redux-actions`は先ほど実装したようなアクションである[Flux Standard Action](https://github.com/acdlite/flux-standard-action)モデルを実装したもので、このモデルに従っていれば`redux-actions`はシームレスに導入できます。

- `yarn add redux-actions`を忘れずに実行します。

(原文: [10 - Immutable JS and Redux Improvements](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/10-immutable-redux-improvements))


# 11 - Mocha、Chai、Sinonによるテスティング

## MochaとChai

- `src/test`フォルダを作ります。このフォルダはアプリケーションのフォルダ構造を反映していて、`src/test/client`フォルダも同様に作ります(`server`フォルダと`shared`フォルダも必要なら作っても構わないのですが、ここではテストを書きません)。

- `src/test/client`フォルダ内に`state-test.js`ファイルを作ります。これはReduxアプリケーションのライフサイクルをテストするのに使われます。

メインのテスティングフレームワークには、[Mocha](http://mochajs.org/)を使うことにします。Mochaは使いやすく、機能が豊富で、今のところ[最もよく使われるJavaScriptのテスティングフレームワーク](http://stateofjs.com/2016/testing/)です。また、フレキシブルでモジュラー化されています。特に、好きなアサーションライブラリを使うことができます。[Chai](http://chaijs.com/)は、たくさんの[plugin](http://chaijs.com/plugins/)を持つ素晴らしいアサーションライブラリで、異なるアサーションスタイルを選ぶことができます。

- `yarn add --dev mocha chai`を実行して、MochaとChaiをインストールします。

`state-test.js`を以下のように書きます:

```javascript
/* eslint-disable import/no-extraneous-dependencies, no-unused-expressions */

import { createStore } from 'redux';
import { combineReducers } from 'redux-immutable';
import { should } from 'chai';
import { describe, it, beforeEach } from 'mocha';
import dogReducer from '../../client/reducers/dog-reducer';
import { makeBark } from '../../client/actions/dog-actions';

should();
let store;

describe('App State', () => {
  describe('Dog', () => {
    beforeEach(() => {
      store = createStore(combineReducers({
        dog: dogReducer,
      }));
    });
    describe('makeBark', () => {
      it('should make hasBarked go from false to true', () => {
        store.getState().getIn(['dog', 'hasBarked']).should.be.false;
        store.dispatch(makeBark());
        store.getState().getIn(['dog', 'hasBarked']).should.be.true;
      });
    });
  });
});
```

さて、この全体を解析してみましょう。

まず、`chai`の`should`アサーションスタイルをどのようにimportしているのかを注意してみてください。これを使うと`mynumber.should.equal(3)`といった、ちょっと巧妙な構文を使ってアサートできるようになります。どんなオブジェクトに対しても`should`を呼び出せるように、何よりも前に`should()`を実行しなければなりません。これらのアサーションには、 `mybook.should.be.true`のように*式(expressions)*であるものがあり、ESLintはこのような書き方に警告を出します。そのため、ファイルの先頭に`no-unused-expressions`ルールを無効にするESLintのコメントを追加しています。

Mochaのテストは木構造のような階層構造で動作します。ここでは、アプリケーションの状態の`dog`属性に影響する`makeBark`関数をテストしたいので、テストの階層は`describe()`で表現した通り、`App State > Dog > makeBark`という形になります。`it()`が実際のテスト関数で、`beforeEach()`は`it()`の各テストの前に実行される関数になります。この例では、各テストが走る前に新しい状態が必要です。そこで、ファイルの先頭で変数`store`を宣言し、このファイル内での全てのテストで使えるようにしています。

`makeBark`テストは明示的に書かれていますが、`it()`内に文字列で与えられている説明によってさらにわかりやすくなっています: ここでは`makeBark`の呼び出しによって`hasBarked`が`false`から`true`に変わるのをテストしています。

さあ、テストを実行してみましょう！

- `gulp-mocha`プラグインを使って、`gulpfile.babel.js`に以下の`test`タスクを作ります:

```javascript
import mocha from 'gulp-mocha';

const paths = {
  // [...]
  allLibTests: 'lib/test/**/*.js',
};

// [...]

gulp.task('test', ['build'], () =>
  gulp.src(paths.allLibTests)
    .pipe(mocha())
);
```

- もちろん、`yarn add --dev gulp-mocha`で実行します。

このように、テストは`lib`にトランスパイルされたコードを実行します。これが`test`が`build`の前提条件になっている理由です。`build`も`lint`という前提条件を持っており、そして最後に、`test`が`main`の前提条件になります。これにより、`default`は次のようなタスクの連鎖ができます: `lint` > `build` > `test` > `main`。

- `main`の前提条件を`test`に変えます:

```javascript
gulp.task('main', ['test'], () => /* ... */ );
```

- `package.json`の`"test"`スクリプトを`"test": "gulp test"`に変更します。こうすると`yarn test`でテストを実行できるようになります。`test`は例えばCIサービスのようなツールで自動的に呼ばれる標準のスクリプトでもあるため、必ずテストタスクはここに書くべきです。`yarn start`はWebpackのクライアントバンドルを作る前にテストを実行するため、全てのテストにパスすればビルドするだけになります。

- `yarn test`または`yarn start`を実行すると、テスト結果が出力されます。おそらくグリーンになっているはずです。

## Sinon

ユニットテストで*fake*を使いたくなることがあります。たとえば、`deleteDatabases()`という関数の呼び出しを含む`deleteEverything`という関数があったとします。`deleteDatabases()`の実行には様々な副作用があるため、テストスイートを走らせる際には実行したくありません。

[Sinon](http://sinonjs.org/)は **スタブ** (とその他もろもろ)を提供するテスティングライブラリで、`deleteDatabases`を無効化し実際に呼び出すことなく監視のみ行うようになります。これにより、呼ばれたかどうか、どのような引数で呼ばれたかどうかといったことをテストできるようになります。これはAJAXの呼び出しをフェイクしたり避けたりする場合によく使われます - バックエンド上の副作用を起こしうるような場合です。

ここでは、アプリに対して、`src/shared/dog.js`にある`Dog`クラスのメソッド`barkInConsole`を追加してみます。

```javascript
class Dog {
  constructor(name) {
    this.name = name;
  }

  bark() {
    return `Wah wah, I am ${this.name}`;
  }

  barkInConsole() {
    /* eslint-disable no-console */
    console.log(this.bark());
    /* eslint-enable no-console */
  }
}

export default Dog;
```

ユニットテストで`barkInConsole`を実行すると、 `console.log()` はターミナルへの出力を行います。このようなことは、ユニットテストの文脈における望ましくない副作用であると考えられます。興味があるのは`console.log()`が *正常に呼び出されるかどうか* であり、テストしたいのはどのようなパラメーターが*呼び出されるのか*といったことです。

- 新しいファイル`src/test/shared/dog-test.js`を作り、次のように書き加えます:

```javascript
/* eslint-disable import/no-extraneous-dependencies, no-console */

import chai from 'chai';
import { stub } from 'sinon';
import sinonChai from 'sinon-chai';
import { describe, it } from 'mocha';
import Dog from '../../shared/dog';

chai.should();
chai.use(sinonChai);

describe('Shared', () => {
  describe('Dog', () => {
    describe('barkInConsole', () => {
      it('should print a bark string with its name', () => {
        stub(console, 'log');
        new Dog('Test Toby').barkInConsole();
        console.log.should.have.been.calledWith('Wah wah, I am Test Toby');
        console.log.restore();
      });
    });
  });
});
```

ここでは、Sinonの*stubs*と、その上でChaiのアサーションを使うためのChaiプラグインをimportしています。

- `yarn add --dev sinon sinon-chai`を実行してライブラリをインストールします。

ここでの新しいことは何でしょうか？ 何よりもまず、Chaiプラグインを使うために`chai.use(sinonChai)`を呼び出しています。そして、`it()`文で全ての魔法が発動しています: `stub(console, 'log')`が`console.log`を無効化し監視します。`new Dog('Test Toby').barkInConsole()`が実行されると、新たな`console.log`が用意されます。そして`console.log`を`console.log.should.have.been.calledWith()`で呼び出してテストし、最後に`restore`で`console.log`を元に戻しています。

**重要な注意**: `console.log`をスタブするのはおすすめできません。もしテストが失敗すると、`console.log.restore()`が呼び出されず、そのため`console.log`はターミナルで残りのコマンドをテストしている間中ずっと壊れてしまったままだからです! テストが失敗した時のエラーメッセージも出力できないため、何が起こっているかの情報をほとんど残すことができなくなります。これは大変厄介です。この例は単純なアプリでスタブを説明するためだけのものです。

もしこの章の内容がうまくいっていれば、パスするテストが2つ得られるはずです。

(原文: [11 - Testing with Mocha, Chai, and Sinon](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/11-testing-mocha-chai-sinon))


# 12 - Flow

[Flow](https://flowtype.org/)は静的型チェッカーです。コード内の一貫性のない型を検出し、アノテーションを使って明示的な型宣言を追加することができます。

- トランスパイルの過程でBabelにFlowアノテーションを理解し削除させるため、`yarn add --dev babel-preset-flow`を実行してBabelのFlowプリセットをインストールします。そして、`package.json`の`babel.presets`に`"flow"`を追加します。

- プロジェクトのルートに空の`.flowconfig`ファイルを作ります。

- `yarn add --dev gulp-flowtype`を実行してFlowのGulpプラグインをインストールし、`lint`タスクに`flow()`を追加します:

```javascript
import flow from 'gulp-flowtype';

// [...]

gulp.task('lint', () =>
  gulp.src([
    paths.allSrcJs,
    paths.gulpFile,
    paths.webpackFile,
  ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError())
    .pipe(flow({ abort: true })) // Add Flow here
);
```

`abort`オプションはFlowが問題を検出した場合にGulpタスクを中断させるものです。

これでFlowが実行できるようになりました。

- `src/shared/dog.js`にFlowアノテーションを以下のように追加します:

```javascript
// @flow

class Dog {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  bark(): string {
    return `Wah wah, I am ${this.name}`;
  }

  barkInConsole() {
    /* eslint-disable no-console */
    console.log(this.bark());
    /* eslint-enable no-console */
  }

}

export default Dog;
```

`// @flow`コメントはFlowにこのファイルの型検査をしてほしいことを伝えるものです。それ以外の部分について、Flowアノテーションは、たいてい関数の引数か関数名のあとにコロンがついています。詳細はドキュメントを見てください。

この状態で`yarn start`を実行すると、Flowは問題なく動きますが、ESLintはここで使われている標準的ではない文法について注意してくれることでしょう。Babelのパーサは先ほどインストールした`babel-preset-flow`プラグインのおかげでFlowコンテンツをパースできるようになるため、ESLintがFlowアノテーションを独自に解釈しようとするのではなく、Babelのパーサを使うようになってくれると理想的です。`babel-eslint`パッケージを使えばこれが実現できます。やってみましょう。

- `yarn add --dev babel-eslint`を実行します。

- `package.json`の`eslintConfig`に次のプロパティを追加します: `"parser": "babel-eslint"`

`yarn start`を実行するとlintと型検査が正しく行われるようになったはずです。

これでESLintとBabelで共通のパーサを実行できるようになったので、`eslint-plugin-flowtype`を使ってESLintにFlowのアノテーションをlintさせられるようになりました。

- `yarn add --dev eslint-plugin-flowtype`を実行し、`package.json`の`eslintConfig.plugins`に`"flowtype"`を追加します。また、`eslintConfig.extends`の配列の`"airbnb"`の次に`"plugin:flowtype/recommended"`を追加します。

これで例えば`name:string`というアノテーションを書くと、ESLintはコロンの後ろにスペースを入れるのを忘れていると注意してくれるようになります。

**注意**: `package.json`に書いた`"parser": "babel-eslint"`プロパティは実際には`"plugin:flowtype/recommended"`に含まれるものなので`package.json`から削除することができますが、好みで明示的に残しておいても構いません。このチュートリアルは最小限のセットアップを行うものなので、削除しました(訳注:削除してない??)。

- `src`以下のすべての`.js`と`.jsx`ファイルに対して、`// @flow`を追加し、`yarn test`または`yarn start`を実行します。そしてFlowが提案した部分全部に対して、型アノテーションを追加します。

直感的ではない例としては、`src/client/components/message.jsx`にある以下のものがあります:

```javascript
const Message = ({ message }: { message: string }) => <div>{message}</div>;
```

このように、分割代入している場合、オブジェクトリテラル記法のようなものを使って展開されたプロパティにアノテーションをつけます。

他に見かける例としては、`src/client/reducers/dog-reducer.js`にあるように、FlowはImmutableがデフォルトのexportをつけないと注意してくるというものがあります。この問題は[Immutableの#863](https://github.com/facebook/immutable-js/issues/863)で議論されていますが、2つの回避策があります:

```javascript
import { Map as ImmutableMap } from 'immutable';
// or
import * as Immutable from 'immutable';
```

Immutableがこの件を公式に解決するまで、Immutableコンポーネントをimportする時はどちらか好きな方を使いましょう。個人的には`import * as Immutable from 'immutable'`の方が、短い上に修正された際のリファクタリングも不要なので気に入っています。

**注意**: Flowが型エラーを`node_modules`フォルダで見つけた場合、問題のあるパッケージを無視するため`[ignore]`セクションを`.flowconfig`に追加します(`node_modules`ディレクトリ全体を無視しないようにします)。以下のようになります:

```flowconfig
[ignore]

.*/node_modules/gulp-flowtype/.*
```

この場合、`node_modules/gulp-flowtype`ディレクトリにあるAtomの`linter-flow`プラグインに型エラーが検出されました。これは`// @flow`がついたファイルを同梱していました。

これでlintされて、型検査もテストも通った万全のコードができました!

(原文: [12 - Flow](https://github.com/verekia/js-stack-from-scratch/tree/master/tutorial/12-flow))