前提
SPAではなくて、DOMの操作をjavascriptでやらなければいけない箇所でのみ、導入。主に検索ページのみを考える。
検索ページでは、SEOを考慮するため、SSRもやってみる。
導入方法の検討
クックパッドさんのブログにまとめらている
http://techlife.cookpad.com/entry/2016/07/27/101015
おそらく手軽にやるには、react-railsなのかな?と思いましたが、
今後の発展(SPA)等、もしくは削除を考えるとrailsと切り離して導入したいと思って、webpackを用いて導入しました。
導入
npmを使ってパッケージのインストール
(私は)railsのroot directory配下にpackage.jsonを作成しました。
$ npm init
トランスコンパイラのbabelだったり、reactをインストール
まずはreact。saveをつけて、package.jsonを更新。
$ npm install --save react react-dom
webpackと、開発環境で起動し、随時トランスコンパイルしてくれるdev serverもインストール
$ npm install --save-dev webpack webpack-dev-server
トランスコンパイラのbabel系絡みをインストール。jsxを使いたいのでbabel-preset-reactも。こちらは開発環境に必要なものなので、--save-dev
$ npm install --save-dev babel-loader babel-core babel-preset-react babel-preset-es2015
webpack.configファイルの作成
入力ファイル(jsxファイル等)の指定や、出力ファイルの指定をここで行う。
私の環境では、{Rails.root}/src/javascripts/startup/bundle.jsxに大元の記述をしました。
出力ファイルはSSRをするので、railsの世界に入れるため、app/assets/webpack配下に配置しました。
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
"webpack-bundle": './src/javascripts/startup/bundle.jsx',
},
output: {
path: 'app/assets/webpack',
filename: '[name].js',
publicPath: 'http://localhost:8080/' // webpack-dev-serverのURLを指定する
},
module: {
loaders: [
{
test: /\.js[x]?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query:{
"presets":["react","es2015"]
},
},
],
},
};
package.jsonの編集
scriptsのところに、以下のように実行コマンドを追記。
"scripts": {
"webpack": "webpack --config webpack.config.prod.js --progress --colors",
"dev": "webpack -w --config webpack.config.dev.js"
}
webpackの起動
npm run dev
Server Side Renderingの設定
こちらは、Gemfileにreact_on_railsを追加
https://github.com/shakacode/react_on_rails
gem 'react_on_rails'
Initializerの編集
bunlde install
rails generate react_on_rails:install
config/initializers/react_on_rails.rbを編集する。
主に自分の環境に合わせて以下を編集
config.generated_assets_dir = File.join(%w(app assets webpack))
config.webpack_generated_files = %w( webpack-bundle.js )
config.server_bundle_js_file = "webpack-bundle.js"
実装
あとはrailsのviewで、react_componentメソッドを使い、prerenderをtrueとすれば、SSRとなる。
= react_component("Main", props: {data: @data}, prerender: true)
上記のように、SSRしたいところだけに設置できるので、まあお手軽かなと。