Babelとwebpackを使ってES6でReactを動かすまでのチュートリアル

ES6（ES2015）でReactのコードを書こうと思い、現時点で最も良さそうな環境を構築してみました。

- モジュールの依存関係解決には多機能かつ設定が簡単なwebpack（v4）を使用しています。
- ES6->ES5のトランスパイラはbabelです。（追記:Babel7に対応しました）
- npmが使えることが前提です。

### 開発環境の確認

node.jsとnpmのバージョンは以下を想定しています。異なる場合はうまくいかないかもしれませんのでご注意ください。

```
$ node -v
v10.15.0

$ npm -v
6.11.3
```
### 作業場所の確保と下準備

作業ディレクトリを作成して移動します。

```
mkdir react-es6 && cd $_
```
gitでソースコードを管理する場合は `git init` しておきましょう。

```
git init
```

package.jsonを生成します。初期設定をスキップするため `-y` オプションを付けています。

```
npm init -y
```
以下のpackage.jsonが生成されます。

```package.json
{
  "name": "react-es6",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
```
ソースコードを配置するディレクトリとコンパイルしたコードを生成するディレクトリを作成します。

```
mkdir src dist
```
ここまでが下準備。

## babelとwebpackのインストール


babelの必要なパッケージをインストールします。
`-D`は`--save-dev`と同義で`package.json`の`devDependencies`に自動的に記録するためのオプションです。

```
$ npm i -D @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/register
```

babelの設定ファイルを作成します。

```
touch .babelrc
```
`.babelrc`にはES6を利用するため以下のように記述します。

```.babelrc
{
  "presets": [
    "@babel/preset-env", "@babel/preset-react"
  ]
}
```
次にwebpackとwebpack-cliをインストールします。

```
$ npm i -D webpack webpack-cli
```

webpackのコンフィグファイルを作成します。
ここでは、親ファイルを`webpack.config.js`とし、詳細は`development.js`を読ませることにします。

```
touch webpack.config.js development.js
```

設定ファイルには以下のように記述します。

```webpack.config.js
require('@babel/register'); // development.jsでES6を使えるようにする
module.exports = require('./development');
```
```development.js
import path from 'path'

const src  = path.resolve(__dirname, 'src')
const dist = path.resolve(__dirname, 'dist')

export default {
  mode: 'development',
  entry: src + '/index.jsx',

  output: {
    path: dist,
    filename: 'bundle.js'
  },

  module: {
    rules: [
      {
        test: /\.jsx$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  },

  resolve: {
    extensions: ['.js', '.jsx']
  },

  plugins: []
}
```

## Reactパッケージのインストール

Reactのパッケージをインストールします。
`-S`をつけておくとpackage.jsonの`dependencies`に反映してくれます。

```
npm i -S react react-dom
```

さていよいよReactのコードを書いていきます。
とりあえずシンプルに、ブラウザ上に"Hello React!"と表示させてみましょう。

```
touch src/index.jsx
```

```index.jsx
import React from 'react';
import {render} from 'react-dom';

class App extends React.Component {
  render () {
    return <p> Hello React!</p>;
  }
}

render(<App/>, document.getElementById('app'));
```

なおここまででWebpackを使って上記のコードをビルドすることが可能です。
成功すれば、`dist/bundle.js`が生成されますので確認の意味で実行してみましょう。（やらなくてもいいです）

```
./node_modules/.bin/webpack
```

## webpack-dev-serverのインストール

webpackにはwebpack-dev-serverというモジュールが用意されていて、これを使うとwebサーバーを通して動作確認しながら開発することができます。
また`watchify`などと同様にソースコードの変更を検知して自動的にビルドしてくれるので便利です。

```
$ npm i -D webpack-dev-server html-webpack-plugin
```

development.jsに必要な設定を追記します。

```development.js
import path from 'path'
import HtmlWebpackPlugin from 'html-webpack-plugin' //この行を追記
// 中略
export default {
  // 中略
  plugins: [
    //以下追記
    new HtmlWebpackPlugin({
      template: src + '/index.html',
      filename: 'index.html'
    })
  ]

}
```
index.htmlを用意しておきます。

```
touch src/index.html
```

```index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>React Test</title>
  </head>
  <body>
    <div id="app" />
  </body>
</html>
```

webpack-dev-serverを起動してみましょう。

```
$ ./node_modules/.bin/webpack-dev-server
```
以下のようなビルド結果が出力され、ブラウザから`localhost:8080`にアクセスして、以下のように表示されれば成功です！

```
$ ./node_modules/.bin/webpack-dev-server
ℹ ｢wds｣: Project is running at http://localhost:8080/

// 中略

Child html-webpack-plugin for "index.html":
     1 asset
    Entrypoint undefined = index.html
    [./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html] 351 bytes {0} [built]
    [./node_modules/lodash/lodash.js] 527 KiB {0} [built]
    [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 509 bytes {0} [built]
    [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 519 bytes {0} [built]
ℹ ｢wdm｣: Compiled successfully.
```

次回から`npm start`コマンドでwebサーバーを起動できるようにpackage.jsonに登録しておきましょう。

```package.json
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1", //カンマを足す
  "start": "webpack-dev-server" // 追記する
}
```

さて、ただ"Hello React!"と表示しただけではつまらないので、
少しインタラクティブなアプリケーションにしてみましょう。


まずはwebサーバーを起動しておきます。

```
$ npm start
```
index.jsxを以下のように変更してください。

```index.jsx
import React from 'react'
import { render } from 'react-dom'

class App extends React.Component {
  constructor(props) { 
    super(props)
    this.state = { message: 'something' }
  }

  onChange(e) {
     this.setState( {message: e.target.value} )
  }

  render() {
    return (
      <div>
        <input type="text" onChange = { this.onChange.bind(this) } />
        <p>{ this.state.message }</p>
      </div>
    )
  }
}

render(<App/>, document.getElementById('app'))
```

変更して保存すると自動的にビルドされます。
ブラウザをリロードすると以下のようにテキストエリアに入力した文字列をリアルタイム表示するアプリケーションが動作します。

![react-es6.gif](https://qiita-image-store.s3.amazonaws.com/0/19401/48bfce11-37bc-d6eb-7899-11cbdba4a3d6.gif)

以上です。あとはガシガシReactのコードを書いていくのみ！！

（追記）
最終的なコードはこちらに置きました。
https://github.com/akirakudo/react-es6-tutorial