RailsのフロントエンドにwebpackでビルドされたReactを使うための設定

## 概要

Railsアプリケーション内でフロントエンドにReactを利用するための設定をする。(2018/11/6時点)
Railsアプリケーションの作成から、Railsのフォルダ内にフロントエンドのためのフォルダを作成し、
ビルド、Rails起動でReactで実装したものが見れる部分までの設定を行う。


## 実行環境

* Rails 5.2.1
* node 8.11.4
* npm 5.6.0


## Railsプロジェクトの作成

こちらの記事など参考にしていただけると嬉しいです。
[ローカル環境に諸々をインストールせずにRails新プロジェクトを作成する - Qiita](https://qiita.com/guri3/items/baa70d981f7daa4e91a6)
また、Reactで作成したjsファイルを反映させる対象のページを作成します。
以下のファイルをそれぞれ編集・作成します。

```ruby:config/route.rb
Rails.application.routes.draw do
  root to: 'home#index'
end
```

```ruby:app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
  end
end
```

```erb:app/views/home/index.html.erb
<div id="app"></div>
<%= javascript_include_tag 'webpack/app.js' %>
```

Railsプロジェクトの`config/initializes/assets.rb`に以下の記述を追加します。

```rb:config/initializes/assets.rb
Rails.application.config.assets.precompile += %w( webpack/app.js )
```

また、このままではRailsのprecompileにビルドしたファイルが含まれ、読み込み時にエラーが発生するため、
`app/assets/javascripts/application.js`に以下を追加します。
これは、本来`require_tree`で全て読み込まれるはずのjsファイルの対象から、指定したファイルを除外するための命令を記述しています。

```js:app/assets/javascripts/application.js
//= stub webpack/app
```

この時点では、Reactによるjsファイルが作成されていないため、実行はできません。


## Reactプロジェクトの作成

新規作成したRailsプロジェクトの中に`front`フォルダを作成します。

```sh
$ mkdir front && cd front
```

frontフォルダ内でnpmライブラリのインストールを行います。

```sh
$ npm init -y
# -Dは--save-devの意味
$ npm install -D webpack webpack-cli
$ npm install -D @babel/core babel-loader @babel/preset-env @babel/preset-react
# -Sは--saveの意味
$ npm install -S react react-dom
```

`front`フォルダ内に`src`フォルダを作成し、App.jsとindex.jsを作成します。

```jsx:front/src/App.js
import React from "react";

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

export default App;
```

```jsx:front/src/index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

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


### webpackを使用したビルド設定を行う

`.babelrc`を作成します。

```json:front/.babelrc
{
  "presets": ["@babel/env", "@babel/react"]
}
```


`webpack.config.js`を作成します。

```js:front/webpack.config.js
// Railsアプリのパスを指定するのに必要
const path = require("path");

module.exports = {
  entry: {
    app: "./src/index.js"
  },
  output: {
    // Railsアプリのassets内にビルドしたファイルを置くように設定
    path: path.resolve(__dirname, "../app/assets/javascripts/webpack"),
    filename: "[name].js"
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: {
          loader: "babel-loader"
        },
        exclude: /node_modules/
      }
    ]
  }
};
```

開発の利便性のために`package.json`に開発用ビルドコマンドを追加します。

```js:front/package.json
{
  // ...省略
  "scripts": {
     "webpack-watch": "webpack -w"
  },
  // ...省略
}
```

`front`ディレクトリ内で以下のコマンドを叩くことでファイルのビルド・監視を行えるようになっているか確認します。
`app/assets/javascripts/webpack/app.js`が作成されていたらOKです。

```sh
$ npm run webpack-watch
```

また別のターミナルを開いてRailsアプリケーションを起動してみます。

```sh
$ bundle exec rails server
```

http://localhost:3000 にアクセスし、このような画面が表示されていたら完了です。
<img width="584" alt="スクリーンショット 2018-11-06 23.19.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/174052/7dba1d92-f52d-00df-8400-ecaa5f85461d.png">