LoginSignup
32
28

More than 5 years have passed since last update.

RailsとReact + Webpackでサーバサイドレンダリング

Last updated at Posted at 2016-06-12

WebpackでReactをビルドしたものをRailsでサーバサイドレンダリングする方法をまとめました。

Webpack側

$ npm i -D webpack babel babel-loader babel-core
$ npm i -D babel-preset-react babel-preset-es2015

Reactのコンポーネントのテストを書く場合はreactreact-domをインストールする必要があります。
そうでない場合はインストールしなくても、react-railsにこれらが含まれているので問題ありません。

Webpackの設定

Reactのコンポーネントをreactディレクトリに配置して、ビルドしたものはapp/assets/javascripts/componentsに出力されるようにします。
reactreact-domはreact-railsのものを利用するので、externalsに設定しておきます。

webpack.config.js
const DEBUG = !process.argv.includes('--release');

module.exports = {
  cache: DEBUG,
  debug: DEBUG,

  entry: {
    Hoge: './react/Hoge.jsx',
  },
  output: { path: './app/assets/javascripts/components', filename: '[name].js' },
  devtool: DEBUG ? 'inline-source-map' : false,
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
  },
}

Reactのコンポーネント

Reactのコンポーネントは以下のように、サーバサイドレンダリングするオブジェクトをwindowのプロパティとして出力します。

react/Hoge.jsx
import React from 'react';

class Hoge extends React.Component {
  render() {
    return (
      <div>
        hogehoge
      </div>
    )
  }
}

window.Hoge = Hoge;

package.json

package.jsonにはscriptを設定します。
開発する時はnpm run buildnpm run watchコマンドを使うといいと思います。

package.json
{
  "scripts": {
    "build": "webpack",
    "watch": "webpack --watch",
    "release": "webpack --release"
  },
}

Rails側

react-railsをインストール

Gemfile
gem 'react-rails'
$ bundle install
$ bundle exec rails g react:install

config.react.variantを設定

config/environments/development.rb
 Rails.application.configure do
+  config.react.variant = :development
 end
config/environments/production.rb
 Rails.application.configure do
+  config.react.variant = :production
 end

production環境の設定

server_rendering.jsを新たに作成します。

app/assets/javascripts/server_rendering.js
//= require react-server
//= require components

それぞれのファイルに追記します。

config/initializers/assets.rb
Rails.application.config.assets.precompile += %w( server_rendering.js )
config/environments/production.rb
 Rails.application.configure do
   config.react.variant = :production
+  config.react.server_renderer_options = {
+    files: ["server_rendering.js"],
+  }
 end

Precompile時にWebpackでビルドするために、以下のファイルを新たに作成します。

lib/tasks/before_precompile.rake
task :build_react do
  sh "npm run release"
end

Rake::Task["assets:precompile"].enhance(%i(build_react))

Reactのコンポーネントのレンダリング

react_componentに表示したいコンポーネントと、引数を渡します。
題3引数に{prerender: true}を渡してサーバサイドレンダリングを有効にしています。

index.html.erb
<%= react_component('Hoge', {}, {prerender: true}) %>

おわりに

今回編集および追加したファイルは以下のようになっています。

rails_root
├── app/
│   └── assets
│       └── javascripts
│           ├── application.js
│           ├── components
│           ├── components.js
│           └── server_rendering.js
├── config/
│   ├── environments
│   │   ├── development.rb
│   │   └── production.rb
│   └── initializers
│       └── assets.rb
├── lib/
│   └── tasks
│       └── before_precompile.rake
├── react/
│   └── Hoge.jsx
├── Gemfile
├── package.json
└── webpack.config.js

app/assets/javascripts/componentsはビルドするたびに変更が発生するので、gitを使って複数人で開発しているとコンフリクトしやすいです。
gitignoreにapp/assets/javascripts/components以下のファイルを無視するように設定しておくべきかもしれません。

参考

32
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
28