react.jsをRails4.2.1で動かしてみたのでメモ。
今回作成したソースコードはysm001/rails-react-sampleに置いてあります。
使い方
npm install
bundle install
npm start
railsプロジェクトの作成
$ rails new rails_react
$ cd rails_react
package.json
npm initとかでpackage.json生成。
{
"name": "rails-react",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
}
必要なmoduleのinstall
以下のコマンドを実行して必要なmoduleをinstallする。
npm install --save-dev browserify reactify watchify
npm install --save react react-router react-tap-event-plugin
browserify: クライアントでもrequireを使ってnode moduleの読み込みが可能にするmodule
reactify: jsxをjsに変換するmodule
watchify: ファイルの変更を検知してbrowserifyしなおしてくれるmodule
reactみたいなでっかいファイルを毎回browserifyするとめちゃくちゃ重いので、watchify使って差分だけbrowserifyする。
npm scripts
以下のscriptをpackage.jsonに追記。
"scripts": {
"bundle": "browserify -t reactify app/assets/javascripts/app.jsx > app/assets/javascripts/bundle.js",
"watch-js": "watchify -t reactify app/assets/javascripts/app.jsx -o app/assets/javascripts/bundle.js -v",
"start": "npm run watch-js & rails s"
}
bundle: app.jsxをbrowserifyしてbundle.jsに吐く
watch-js: app.jsを監視して、変更点をbundle.jsに適用
start: ファイル監視 & railsサーバ起動
application.jsの変更
依存関係にあるファイルはrequireで読み込んでいくので、application.js
に書いてあるrequire_tree .
は不要。
なので、app/assets/javascripts/application.js
から
//= require_tree .
を削除して
//= require bundle.js
を追加。
表示するページの作成
テスト用に適当にページを作ります。
app/assets/javascripts/app.jsx
にアプリケーションのメインとなる処理を記述。
とりあえず、以下のような感じでRouterを使った処理を書いてみました。
(function() {
var React = require('react');
window.React = React; // Reactオブジェクトだけは外に出しておく
var injectTapEventPlugin = require("react-tap-event-plugin");
injectTapEventPlugin();
var Router = require('react-router');
var AppRoutes = require('./app-routes.jsx');
$(function() {
Router.run(AppRoutes, function (Handler) {
React.render(<Handler/>, document.body);
});
});
}) ();
Routerも適当になんか書いておく。
var React = require('react');
var Router = require('react-router');
var DefaultRoute = Router.DefaultRoute;
var Route = Router.Route;
var RouteHandler = Router.RouteHandler;
var Root = React.createClass({
render: function() {
return (
<div>
<p>header</p>
<RouteHandler/>
<p>footer</p>
</div>
);
}
});
var PathA = React.createClass({
render: function() { return <p>path A</p>; }
});
var PathB = React.createClass({
render: function() { return <p>path B</p>; }
});
var AppRoutes = (
<Route name="app" path="/" handler={Root}>
<DefaultRoute handler={PathA}/>
<Route name="path-a" path="/path-a" handler={PathA} />
<Route name="path-b" path="/path-b" handler={PathB} />
</Route>
);
module.exports = AppRoutes;
表示用にコントローラを用意。react#indexで何か表示してみることにします。
bundle exec rails g controller react index
実行
npm start
した後、http://localhost:3000/react/index
にアクセスすると
header
path a
footer
と表示されているかと思います。
http://localhost:3000/react/index#/path-b
にアクセスするとpath aがpath bに書き変わり、正常に動作していることが確認できます。
また、app.jsx
やapp-routes.jsx
を編集すると、ファイルの更新が自動でbundle.js
に反映されて、リロードした際に変更点が反映されているのが確認できるかと思います。