フロントエンド始めるならJavaScript Stack from Scratchのチュートリアル その2

# はじめに
この記事は[これ](https://qiita.com/sakahiro/items/63b89a2c6395d9d86ef6)の続きです。

- この記事は補足として使用していただけるといいかなと思います。
- 随時章を追加していきます。
- 間違っている部分があれば優しく教えてください。

# 章ごとのまとめ

## [chapter3](https://github.com/verekia/js-stack-from-scratch/blob/master/tutorial/03-express-nodemon-pm2.md#readme)

#### 1. [Express](http://expressjs.com/)

`Express`はnodeのweb applicationフレームワーク。
このチュートリアルでは、コードを

- `src/client/` ... クライアントサイドの処理を書く。
- `src/shared/`　... clientとserver側で共通に使いたい処理を書く。
- `src/server/` ... サーバー側の処理を書く。

に分けていた。

```bash
yarn add express compression
```

で`express`と[compression](https://github.com/expressjs/compression)を入れて終わり。

*Expressのコード補足*

- WEBPORTは後でherokuにあげるときのために、`process.env.PORT`の値を受け取れるようにしている。
- 2種類の静的なファイルを格納するディレクトリを扱う。一つはgenerateされたファイルを格納する`dist`。もう一つは宣言的なファイルを格納するpublic。
- `app.use(STATIC_PATH, express.static('dist'))`らへんが分からなければ[こちら](http://expressjs.com/ja/starter/static-files.html)

#### 2. [nodemon](https://nodemon.io/)

`nodemon`はファイルが変更された際、nodeサーバーを自動的にリスタートしてくれるユーティリティ。

```bash
yarn add --dev nodemon
```

```javascript:package.json
  "start": "yarn dev:start",
  "dev:start": "nodemon --ignore lib --exec babel-node src/server",
```

こうすれば、lib以外のファイルを変更した時にサーバーを毎回自動的にrestartしてくれる。

#### 3. [PM2](https://nodemon.io/)

`PM2`はnodeのプロセスのモニタリングや管理ができる。

今まではbabel-nodeを使ってサーバーを立ち上げていたけど、productionでは重すぎるので、babelを使用してビルドしたい。新しいビルドの際に毎回以前ビルドされたファイルを消しておくのがgood practiceなので、[rimraf](https://github.com/isaacs/rimraf)を使用する。rimrafはファイルの削除をcross platformで行える。

```bash
yarn add --dev rimraf
```

productionでのビルドのタスクをscriptとして定義する。

```javascript:package.json
  ...
  "prod:build": "rimraf lib && babel src -d lib --ignore .test.js",
  ...
```

次に、pm2を使用するため、pm2と[cross-env](https://github.com/kentcdodds/cross-env)を入れる。
cross-envは、osごとの環境変数設定のシンタックスの違いを吸収してくれる。

```bash
yarn add --dev pm2 cross-env
```

```javascript:package.json
  ...
  "prod:start": "cross-env NODE_ENV=production pm2 start lib/server && pm2 logs",
  "prod:stop": "pm2 delete server",
  ...
```

これで

```bash
yarn prod:build
yarn prod:start
```

すればproduction用サーバが立ち上がる。また、

`ctrl + c` すれば `pm2 logs` コマンドはkillされるが、サーバー自体を落としたい場合は
`yarn prod:stop` すれば良い。

あとは、プッシュの前にビルドが正常にできるか確認するため、

```javascript:package.json
  ...
  "prepush": "yarn test && yarn prod:build",
  ...
```

としておく。


## [chapter4](https://github.com/verekia/js-stack-from-scratch/blob/master/tutorial/04-webpack-react-hmr.md#readme)

#### 1. [Webpack](https://webpack.js.org/)

`Webpack`はモジュールバンドラー。javascriptファイルを(大抵)1つのファイルにまとめるので、クライアントはそのファイルを読み込めばいいようになる。

```bash
yarn add --dev webpack webpack-dev-server babel-core babel-loader
```

`bable-loader`は今まで扱ったbabelと同じようにコードをトランスパイルするプラグインだが、今回はブラウザで動作させるために使っている。
`babel-core`は`babel-loader`とpeer-dependencyなので、一緒に入れている。


*Webpack　コード補足*

- Webpackの設定ファイルにのbabelの変換を適応するために、`.babel.js`という拡張子をつける。
- `entry`は自分のアプリのstarting point
- `output.filename`は生成されるバンドルファイルの名前
- `output.path`は生成されるバンドルファイルが格納されるフォルダ
- `output.publicPath`は生成されるバンドルファイルのフォルダを指し示すURL
- `moduel.rules`はWebpackがどのファイルを取り扱うかの指定
- `resolve`　は指定した拡張子のファイルをimportする時に使用される
- クライアントサイドで新しいESのフィーチャーを使用したければ`yarn add babel-polyfill`して、ファイルで　`import babel-polyfill`　と記述すれば良い。
- `window`や`document`など、ブラウザに関するキーワードを使用する場合、ESlintに引っかからないようにするために

```javascript:.eslintrc.json
  "env": {
    "browser":true
  } 
```

とする。


```javascript:package.json
"scripts": {
  "dev:wds": "webpack-dev-server --progress",
  "prod:build": "rimraf lib dist && babel src -d lib --ignore .test.js && cross-env NODE_ENV=production webpack -p --progress",
  "lint": "eslint src webpack.config.babel.js --ext .js,.jsx",
} 
```

スクリプトを上記のように変更すれば、
開発環境では

```bash
yarn start
```
別ターミナルで

```bash
yarn dev:wds
```

とすれば、正常にアクセスできるようになる。ブラウザ開発ツールのsource内で`webpack://./src`をみて、ES6で書かれた元のファイルが全て確認できるなら、sourcemapがきちんと動いていることを確かめれる。

また、

```bash
yarn prod:build
yarn prod:start
```

して、　http://localhost:8000/static/js/bundle.js にアクセスすれば、Webpackによってビルドされたクライアントサイドのコードを見ることができる。


#### 2. [React](https://reactjs.org/)

`React`はfacebook製のユーザーインターフェースをビルドできるライブラリ。

```bash
yarn add react react-dom
```

reactを書く際にも、ES6のシンタックスチェックと、型チェックをしたいので、

```bash
yarn add --dev babel-preset-react babel-plugin-flow-react-proptypes
```

```javascript:.babelrc
{
  "presets": [
    "react"
  ],
  "plugins": [
    "flow-react-proptypes"
  ]
}
```

とする。

#### 3. [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/)

`Hot Module Replacement`はWebpackの機能の一つで、手動でリロードしなくとも、moduleに変更があった場合にその変更をブラウザに反映してくれる。

今回はreact用に[react-hot-loader](https://github.com/gaearon/react-hot-loader)を入れる。

```bash
yarn add react-hot-loader@next
```

```javascript:webpack.config.babel.js
import webpack from 'webpack'
// [...]
entry: [
  'react-hot-loader/patch',
  './src/client',
],
// [...]
devServer: {
  port: WDS_PORT,
  hot: true,
  headers: {
    'Access-Control-Allow-Origin': '*',
  },
},
plugins: [
  new webpack.optimize.OccurrenceOrderPlugin(),
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NamedModulesPlugin(),
  new webpack.NoEmitOnErrorsPlugin(),
],
```

WebpackのHMRの設定に関しては[ここ](https://webpack.js.org/guides/hot-module-replacement/#enabling-hmr)に記述してある。

pluginがいくつも出てきたが、

- [optimize.OccurrenceOrderPlugin](https://qiita.com/R-Yoshi/items/30282dee7b6d5ddd6622#occurrenceorderplugin)...リンク先の説明を参照してください。
- [HotModuleReplacementPlugin](https://webpack.js.org/plugins/hot-module-replacement-plugin/)...HMRを有効にするために必要なプラグイン
- [NamedModulesPlugin](https://webpack.js.org/plugins/named-modules-plugin/)...HMRを使用している時、moduleの相対パスを表示してくれる(HMRを入れる時にこいつも入れるよう推奨されている)
- [NoEmitOnErrorsPlugin](https://webpack.js.org/plugins/no-emit-on-errors-plugin/)...コンパイル中にエラーがでたemittin_phaseをスキップする。これでerrosを含んだアッセットがemitされないことを保証できる。？(ここはあまりよく分かっていないです。誰かわかる方がいれば)

`devServer.headers`のcross-origin設定に関しては、[こちら](https://github.com/gaearon/react-hot-loader/blob/master/docs/Troubleshooting.md#cant-hot-reload)。

実際にHMRに必要なプラグインは`HotModuleReplacementPlugin`と`NamedModulesPlugin`(推奨)のみ。