react-rails
Pocket

バックエンドをRails5のAPIモード、フロントエンドをReactの環境構築をやってみます。webpackも使います。

もくじ
  1. Rails
  2. フロントエンドの環境構築
  3. Foremanを使う
  4. APIを取得してみる

Rails

まずはAPIモードでRails環境をつくります。

apiモードで始めるには以下のコマンドを打ちます。

rails new sampleapp --api

ファイル一式が完成したら、ディレクトリ移動しておきます。

cd sampleapp/

「rails s」で起動できます。

フロントエンドの環境構築

フロントエンドのコードはclientディレクトリを作り、そこで行います。

./client
├── .babelrc
├── package.json
├── src
│   └── app.js
├── webpack.config.js
├── www
│   ├── bundle.js
│   └── index.html
└── yarn.lock

ここで書いた記事とあまり変わらないので参考に

初めてでもできるwebpackとbabelを使ってみるまで

まずは、clientディレクトリを作り、移動します。

mkdir client && cd client

yarnを使いますが、npmでもOKです。

yarn init -y

パッケージをインストールします。

yarn add babel-core babel-loader babel-preset-es2015 babel-preset-react webpack webpack-dev-server -D

Reactも

yarn add react react-dom

.babelrcとwebpack.config.jsを作ります。

touch .babelrc webpack.config.js

それぞれ以下を追記

.babelrc

{
  "presets": [
    "es2015", "react"
  ]
}

webpack.config.js

const path = require('path');

module.exports = {
  entry: path.join(__dirname, 'src/app.js'),
  output: {
    path: path.join(__dirname, 'www'),
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: 'www',
    port: 4000,
    inline: true
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  }
};

フロントエンド側のportは4000番にしています。Rails側でデフォルトの3000番を使うので。

必要なディレクトリを作ります。srcディレクトリ以下でコーディングをして、wwwに書き出すようにします。

mkdir src www

必要なファイルを作ります。

touch src/app.js www/index.html

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>React</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="bundle.js"></script>
  </body>
</html>

app.js

import React from 'react'
import { render } from 'react-dom'

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

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

以下のコマンドを打つと、www以下にbundle.jsができます。

./node_modules/.bin/webpack

package.jsonにscriptを登録します。

package.json

  // 省略
  "license": "MIT",
  // ここ追記
  "scripts": {
    "start": "webpack-dev-server"
  },
  "devDependencies": {
  // 省略

以下のコマンドでlocalhost:4000が立ち上がります。

yarn start

Hello React!と出ればOKです。

Foremanを使う

これでプロジェクトディレクトリ直下で「rails s」を打てばlocalhost:3000でRailsが起動、clientディレクトリ直下で「yarn start」と打てば、localhost:4000でフロントエンドが起動するようになりました。

ただ、いちいちそれぞれを起動するのは面倒です。。。そこでForemanを使います。

ディレクトリの場所を一つ上に戻っておきます。

cd ../

GemfileにForemanを追加し、bandle installします。

Gemfile

source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

# ここ追記
gem 'foreman'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.1'

# 省略

そして以下を打ちます。

bundle install

次に「Procfile」ファイルを作ります。

touch Procfile

Procfile

rails: bundle exec rails s -p 3000
frontend: cd client;yarn run start

以下を打ち「valid procfile detected (rails, frontend)」と出たらOKです。

foreman check

起動する時は、以下のコマンドを打ちます。

foreman start

起動して、localhost:3000にアクセするとRailsが、localhost:4000にアクセスするとHello React!と出てきます。

これでコマンド一つで同時にそれぞれ起動できるようになりました。

APIを取得してみる

RailsでAPIをつくります。

rails g resource Message text:string

「app/controllers」の中にmessage_controller.rbが作られるので、以下のように修正します。

class MessagesController < ApplicationController
  def index
    messages = Message.all
    render json: messages
  end
end

とりあえず、「db/seeds.rb」でサンプルデータを作ってみます。

Message.delete_all
Message.create!([
  { text: 'Good morning' },
  { text: 'Good afternoon' },
  { text: 'Good evening' }
])

以下のコマンドを打ちます。

bundle exec rake db:migrate db:seed

config/routes.rbも修正しておきます。

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

rails sで起動し、「localhost:3000/messages.json」にアクセスします。

するとjson形式でGood morningとかいろいろ出てきます。

これをReactで取得してみます。

「client/src/app.js」を以下のように修正します。

import React from 'react'
import { render } from 'react-dom'

const REQUEST_URL = 'http://localhost:3000/messages.json'

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      data: []
    };
  }

  componentDidMount() {
    this.fetchData()
  }

  fetchData() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
    .then((responseData) => {
      this.setState({
        data: responseData,
      })
    })
  }

  render(){
    return(
      <ul>
        {this.state.data.map((item) => {
          return (
            <li key={item.id}>{item.text}</li>
          )
        })}
      </ul>
    )
  }
}

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

再び、以下のコマンドで立ち上げます。

foreman start

localhost:4000にアクセスすると、何も表示されないと思います。consoleを見るとエラーが出ていて、localhost3000にアクセスするには許可が入りますと言う感じです。アクセスできるようにもうちょっと修正します。

まずはGemfileの27行目あたりにある「rack-cors」のコメントアウトを外します。なければ追記します。

gem 'rack-cors'

bundle installしておきます。

bundle install

そして、「config/application.rbの下の方にあるコードに追記しておきます。

module Sampleapp
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Only loads a smaller set of middleware suitable for API only apps.
    # Middleware like session, flash, cookies can be added back manually.
    # Skip views, helpers and assets when generating a new resource.
    config.api_only = true

    # ここ追記
    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins 'localhost:4000'
        resource '*', :headers => :any, :methods => [:get, :post, :put, :delete, :options]
      end
    end
  end
end

再び起動

foreman start

今度はlocalhost4000にアクセスすると、以下のようにリスト表示されているはずです。

  • Good morning
  • Good afternoon
  • Good evening

さいごに

APIを作って表示するだけですが、RailsとReactの環境をwebpackを使って作ってみました。次はデータ取得するだけなく、POSTしたりしてみようかと思います。

Pocket

One thought on “webpack + React + Rails5 APIモードで環境構築

Comments are closed.