3.1. Reactの環境構築

Reactを利用するために、フロントエンドビルドツールであるwebpackを利用して開発をすすめます。

Reactをビルドするにあたり、webpackをそのまま利用する方法と、Railsからwebpackを簡単に利用できるようにしたwebpackerというGemを使う方法があります。

  1. webpackをそのまま利用する

    • 利点
      • Railsに詳しくなくても扱える(ビルドはRailsとは独立して考えればよい)
    • 欠点
      • ボイラープレート(アプリの雛形)や Create React App などのツールを使わないと初期の環境構築が難しい
      • RailsとReactを同時にデプロイする仕組みを考える必要がある
  2. webpackerを利用する

    • 利点
      • 複雑なwebpackの設定ファイルが隠蔽されているので、webpackに慣れていない場合でも容易に環境構築ができる
      • Railsのアセットと一緒にwebpack buildしたアセットも容易にデプロイできる
      • ヘルパーが用意されており、RailsのViewからwebpackerでビルドしたファイルを簡単に呼び出せる
    • 欠点
      • webpackの最新版にWebpackerが追いついていかない(=最新バージョンをすぐに利用できない)おそれがある

webpackをそのまま利用するかwebpackerを利用するかは、システムの設計方針によっても変わります。

Railsとフロントエンド(Javascript/View)を完全に分離して開発したい場合はwebpackをそのまま利用すべきです。 逆にRailsのエコシステムにのりつつReactを導入したい場合はwebpackerを利用するのをおすすめします。

3.1.1. webpackを利用してビルドする

webpackを利用して、Hello Worldを作成しましょう。

3.1.1.1. Reactアプリを新規作成する

Create React App を利用すると、新規の設定済みReact + Webpack プロジェクトを容易に作成でき、 複雑なwebpackの初期設定をしなくて済みます。

Javascriptのパッケージマネージャには、以降yarnを利用します。 次のコマンドでインストールしてください。

npm install -g yarn

Create React App はグローバルなパッケージとしてインストールする必要があります。

yarn global add create-react-app

Create React App をインストール後、次のコマンドでReactアプリを作成します。

create-react-app hello-react

コマンド実行後に次のファイルが生成されます。

$ tree -I 'node_modules'

.
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── registerServiceWorker.js
└── yarn.lock

3.1.1.2. Reactアプリを起動する

作成したreactプロジェクトディレクトリ内で、次のコマンドを使い development 環境で開発用サーバを起動します。

yarn start

起動後に表示されているアドレスにアクセスすると、Reactアプリが表示されることを確認してください。

../_images/hello-react-app-screen.png

src/App.js には画面表示用のコンポーネントがあります。

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default App;

h1タグ、Welcome to React の文字列を適当なものに変更すると、 自動でビルドが走り画面に表示された文字列が変化していることを確認してください。

3.1.1.3. Reactアプリをビルドする

yarn build コマンドを利用することで、作成したReactアプリのProduction用js/cssファイルを作成することができます。

$ yarn build

yarn run v1.1.0
$ react-scripts build
Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

  38.06 KB  build/static/js/main.a3b22bcc.js
  299 B     build/static/css/main.c17080f1.css

build ディレクトリ以下に作成されたファイルは、そのままサーバに配置することができます。

$ tree build/

build/
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── service-worker.js
└── static
    ├── css
    │   ├── main.c17080f1.css
    │   └── main.c17080f1.css.map
    ├── js
    │   ├── main.a3b22bcc.js
    │   └── main.a3b22bcc.js.map
    └── media
        └── logo.5d5d9eef.svg

4 directories, 10 files

3.1.2. webpackerを利用してビルドする

webpackerを利用してReactをビルドしてみましょう。 webpackerはRubyのgemでありwebpackのラッパーでもあります。webpackerはRailsと組み合わせて使うことを想定しています。

以下手順でRailsアプリからReactを呼び出します。

  1. Rails を新規作成する
  2. RailsのControllerとView、Routingを定義する
  3. Reactコンポーネントを作成する
  4. View から Reactを呼び出す

3.1.2.1. Railsアプリを新規作成する

gemコマンドを使ってRailsを導入します。

gem install rails

rails new コマンドで新規Rails + Reactアプリケーションを作成します。

rails new hello-react-rails --webpack=react --database=mysql

作成したRailsアプリディレクトリの中で次のコマンドを実行し、データベースの初期化をします。

bundle exec rake db:create db:migrate

この状態でRailsを起動してみましょう。 次のコマンドでサーバを起動することができます。

bundle exec rails server

更に、Webpackでのビルドをするために webpack-dev-server も別途起動する必要があります。

bin/webpack-dev-server

ブラウザで http://0.0.0.0:3000 にアクセスすると、次のようなRailsの初期画面が表示されることを確認してください。

../_images/hello-ur-on-rails.png

3.1.2.2. Controller/ViewとRoutingを追加する

Hello World表示用の Controller/View を作成します。 次のコマンドで indexアクションを持った DashboardsController を作成します。

bundle exec rails generate controller dashboards index

app/controllers/dashboards_controller.rb 、app/views/dashboards/index.html.erb が新規作成されます。

class DashboardsController < ApplicationController
  def index
  end
end
<h1>Dashboards#index</h1>
<p>Find me in app/views/dashboards/index.html.erb</p>

config/routes.rb には routingが追加されています。

Rails.application.routes.draw do
  get 'dashboards/index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

Controller、View、およびRoutingを追加することで、画面にアクセスできるようになります。

http://0.0.0.0:3000/dashboards/index にアクセスすると、次の画面が表示されます。

../_images/hello-new-dashboard-rails.png

HTMLは app/views/dashboards/index.html.erb に記述します。 中身を適当な文字列に書き換えて画面を更新してみてください。

3.1.2.3. Reactコンポーネントを作成する

webpackを使ってビルドするjavascriptファイルは、app/javascript 以下に配置します。 app/assets/javascript ではないので注意してください。

app/javascript 以下は webpacker (webpack) でビルドされるファイルを配置し、 app/assets/javascript は Sprocketsでコンパイルするファイルを配置します。

SprocketsとはRailsが利用しているアセット管理用のライブラリで、js/css等のアセットのコンパイル等を担っています。 SprocketsではES6のコンパイルはできませんので、ES6形式のJSは app/javascript に配置しwebpackにビルドさせましょう。

app/javascript/packs/hello_react.jsx に以下ファイルを配置します。 RailsのViewから直接呼び出すエントリーポイントとなるjavascriptは、app/javascript/packs 以下に配置する必要があります。

// app/javascript/packs/hello_react.jsx

import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

const Hello = props => (
  <div>Hello {props.name}!</div>
)

Hello.defaultProps = {
  name: 'David'
}

Hello.propTypes = {
  name: PropTypes.string
}

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <Hello name="React" />,
    document.body.appendChild(document.createElement('div')),
  )
})

このファイルをViewから呼び出してみましょう。 app/views/dashboards/index.html を以下のように書き換えます。

<h1>Dashboards#index</h1>
<p>Find me in app/views/dashboards/index.html.erb</p>

<%= javascript_pack_tag 'hello_react' %>

hello_react の部分は app/javascript/packs 以下のファイル名を指定します。 この状態でdashboards/index画面を更新してみましょう。

../_images/hello-react-rails-2.png

Hello React! という部分は React を使ってレンダリングしています。

app/javascript/packs/hello_react.jsx の Hello コンポーネントを次のように書き換えてみましょう。

import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

class Hello extends React.Component {
  render() {
    return (
      <div>
        こんにちは、React<br />
        props  {this.props.name} のように利用できます。
      </div>
    );
  }
}

Hello.defaultProps = {
  name: 'David'
}

Hello.propTypes = {
  name: PropTypes.string
}

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <Hello name="React" />,
    document.body.appendChild(document.createElement('div')),
  )
})

画面をリロードすると次のように表示されます。

../_images/hello-react-rails-3.png