RailsでReact.jsと言えばreact-railsのgemが有名ですが、react_on_railsというものもあるので使ってみた、というかジェネレーターで作成されるサンプル(Hello World)を動かすまでやってみました。
環境
- OS: CentOS 6.7 64bit (VirtualBox)
- Ruby: 2.2.2
- node: 5.4.1
- npm: 3.3.12
1. まずはRailsプロジェクトの作成
[root@localhost rails]# mkdir react_on_rails_sample
[root@localhost rails]# cd react_on_rails_sample/
[root@localhost react_on_rails_sample]# bundle init
Writing new Gemfile to /var/rails/react_on_rails_sample/Gemfile
[root@localhost react_on_rails_sample]# vi Gemfile
------------------------------
# A sample Gemfile
source "https://rubygems.org"
gem "rails" ←コメントアウトを外す
------------------------------
[root@localhost react_on_rails_sample]# bundle install --path=tmp/bundler
[root@localhost react_on_rails_sample]# bundle exec rails new .
exist
create README.rdoc
create Rakefile
create config.ru
create .gitignore
conflict Gemfile
Overwrite /var/rails/react_on_rails_sample/Gemfile? (enter "h" for help) [Ynaqdh] Y
force Gemfile
create app
create app/assets/javascripts/application.js
・・・
[root@localhost react_on_rails_sample]# vi Gemfile
---------------------
gem 'react_on_rails' ←末尾に追加
---------------------
[root@localhost react_on_rails_sample]# bundle install
gemをグローバルにインストールしたくないので、bundle installでpathオプションを指定しています。
2. react_on_railsのサンプルを試してみる
react_on_railsのGetting Startedをやっていきます。
[root@localhost react_on_rails_sample]# bundle exec rails generate react_on_rails:install --help
Running via Spring preloader in process 2638
Usage:
rails generate react_on_rails:install [options]
Options:
-R, [--redux], [--no-redux] # Install Redux gems and Redux version of Hello World Example. Default: false
-S, [--server-rendering], [--no-server-rendering] # Add necessary files and configurations for server-side rendering. Default: false
-j, [--skip-js-linters], [--no-skip-js-linters] # Skip installing JavaScript linting files. Default: false
-L, [--ruby-linters], [--no-ruby-linters] # Install ruby linting files, tasks, and configs. Default: false
-H, [--heroku-deployment], [--no-heroku-deployment] # Install files necessary for deploying to Heroku. Default: false
-b, [--skip-bootstrap], [--no-skip-bootstrap] # Skip integrating Bootstrap and don't initialize files and regarding configs. Default: false
[--ignore-warnings], [--no-ignore-warnings] # Skip warnings. Default: false
・・・
helpオプションで利用できるオプションを確認しました。
今回はサーバーサイドレンダリングやりたいのでSオプションを指定します。
[root@localhost react_on_rails_sample]# bundle exec rails generate react_on_rails:install -S
Running via Spring preloader in process 2727
fatal: Not a git repository (or any of the parent directories): .git
ERROR: You have uncommitted code. Please commit or stash your changes before continuing
ERROR: react_on_rails generator prerequisites not met!
エラーが出ました。。
どうやらgit管理していないといけないようなので、git init〜commitまでします。
[root@localhost react_on_rails_sample]# git init
Initialized empty Git repository in /var/rails/react_on_rails_sample/.git/
[root@localhost react_on_rails_sample]# git add .
[root@localhost react_on_rails_sample]# git commit -m "init"
[master (root-commit) 1d66a8b] init
40 files changed, 1049 insertions(+), 0 deletions(-)
・・・
それでは、改めて実行。
[root@localhost react_on_rails_sample]# bundle exec rails generate react_on_rails:install -S
Running via Spring preloader in process 2776
ERROR: You have uncommitted code. Please commit or stash your changes before continuing
ERROR: react_on_rails generator prerequisites not met!
git commitしたにも関わらずエラーが出ます。。
調べてみたところ下記の箇所でgit commitしているかチェックしています。
module ReactOnRails
module GitUtils
def self.uncommitted_changes?(message_handler)
return false if ENV["COVERAGE"]
status = `git status`
return false if status.include?("nothing to commit, working directory clean")
error = "You have uncommitted code. Please commit or stash your changes before continuing"
message_handler.add_error(error)
true
end
end
end
Gitのバージョンが違うのかgit statusした時のメッセージが違うため、あのエラーメッセージが表示されているようです。
現在の環境のGitのバージョンは1.7.1です。バージョンアップした方がいいでしょうが、面倒くさいのでソースコードいじりました。(そっちも面倒くさいだろ!というツッコミはなしです
【変更前】
return false if status.include?("nothing to commit, working directory clean")
【変更後】
return false if status.include?("nothing to commit (working directory clean)")
それでは気を取り直して。
[root@localhost react_on_rails_sample]# bundle exec rails generate react_on_rails:install -S
Running via Spring preloader in process 2857
route get 'hello_world', to: 'hello_world#index'
create client/assets
create client/assets/stylesheets
create client/assets/fonts
create client/assets/fonts/.keep
create client/assets/images
create client/assets/images/.keep
append .gitignore
prepend app/assets/javascripts/application.js
gsub app/assets/javascripts/application.js
gsub app/assets/javascripts/application.js
gsub app/assets/javascripts/application.js
gsub app/assets/javascripts/application.js
create client/app/bundles/HelloWorld/components
create client/app/bundles/HelloWorld/containers
create client/app/bundles/HelloWorld/startup
create app/controllers/hello_world_controller.rb
create config/initializers/react_on_rails.rb
create client/.babelrc
create client/index.jade
create client/server.js
create client/webpack.client.base.config.js
create client/webpack.client.rails.config.js
create REACT_ON_RAILS.md
create client/REACT_ON_RAILS_CLIENT_README.md
create package.json
create Procfile.dev
create Procfile.dev-hot
create app/views/hello_world/index.html.erb
create client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx
create client/webpack.client.hot.config.js
create client/package.json
append Gemfile
create client/app/bundles/HelloWorld/startup/clientRegistration.jsx
create client/webpack.server.rails.config.js
create client/app/bundles/HelloWorld/startup/serverRegistration.jsx
create lib/tasks/linters.rake
create lib/tasks/assets.rake
append config/initializers/assets.rb
create client/app/bundles/HelloWorld/containers/HelloWorld.jsx
create client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx
create client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx
create client/.eslintrc
create client/.eslintignore
create client/.jscsrc
create app/assets/stylesheets/_bootstrap-custom.scss
create client/assets/stylesheets/_post-bootstrap.scss
create client/assets/stylesheets/_pre-bootstrap.scss
create client/assets/stylesheets/_react-on-rails-sass-helper.scss
create client/bootstrap-sass.config.js
append app/assets/stylesheets/application.scss
gsub app/assets/stylesheets/application.scss
gsub app/assets/stylesheets/application.scss
append Gemfile
append app/assets/javascripts/application.js
What to do next:
- Ensure your bundle and npm are up to date.
bundle && npm i
- Run the npm rails-server command to load the rails server.
npm run rails-server
- Visit http://localhost:3000/hello_world and see your React On Rails app running!
今度は上手くいきました。
次にやることは、What to do nextに書いてあるのでその通りに実行していきます。
[root@localhost react_on_rails_sample]# bundle && npm i
Don't run Bundler as root. Bundler can ask for sudo if it is needed, and
installing your bundle as root will break this application for all non-root
users on this machine.
Fetching gem metadata from https://rubygems.org/...........
・・・
Bundled gems are installed into ./tmp/bundler.
npm WARN lifecycle react-webpack-rails-tutorial@1.1.1~postinstall: cannot run in wd %s %s (wd=%s) react-webpack-rails-tutorial@1.1.1 cd client && npm install /var/rails/react_on_rails_sample
またエラーです。
bundle installには成功したようですが、その後のnpm installに失敗したようです。
念のためnpm installだけ実行してみます。
[root@localhost react_on_rails_sample]# npm install
npm WARN lifecycle react-webpack-rails-tutorial@1.1.1~postinstall: cannot run in wd %s %s (wd=%s) react-webpack-rails-tutorial@1.1.1 cd client && npm install /var/rails/react_on_rails_sample
エラーは特に変わらないですね。。
調べてみましたが、なぜpostinstallが失敗しているかの原因と解決策が分からなかったので、とりあえずpostinstallが実行するコマンドをそのまま実行してみます。
※原因と解決方法分かったのでコメントに書きました。
[root@localhost react_on_rails_sample]# cd client && npm install
npm WARN install Couldn't install optional dependency: Unsupported
npm WARN deprecated bootstrap-sass-loader@1.0.10: Replaced by bootstrap-loader. Please upgrade.
npm WARN deprecated npmconf@2.1.2: this package has been reintegrated into npm and is now out of date with respect to npm
npm WARN deprecated lodash@1.0.2: lodash@<3.0.0 is no longer maintained. Upgrade to lodash@^4.0.0
npm WARN prefer global jsonlint@1.6.2 should be installed with -g
npm WARN prefer global node-gyp@3.2.1 should be installed with -g
・・・
ちょっとWARNが出てますが、大方インストールできたようです。(WARNは後で解決しましょう。。
そして、次のコマンドnpm run rails-serverを実行します。
[root@localhost react_on_rails_sample]# npm run rails-server
> react-webpack-rails-tutorial@1.1.1 rails-server /var/rails/react_on_rails_sample
> echo 'visit http://localhost:3000/hello_world' && foreman start -f Procfile.dev
visit http://localhost:3000/hello_world
sh: foreman: コマンドが見つかりません
npm ERR! Linux 2.6.32-573.12.1.el6.x86_64
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "rails-server"
npm ERR! node v5.4.1
npm ERR! npm v3.3.12
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! react-webpack-rails-tutorial@1.1.1 rails-server: `echo 'visit http://localhost:3000/hello_world' && foreman start -f Procfile.dev`
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the react-webpack-rails-tutorial@1.1.1 rails-server script 'echo 'visit http://localhost:3000/hello_world' && foreman start -f Procfile.dev'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the react-webpack-rails-tutorial package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! echo 'visit http://localhost:3000/hello_world' && foreman start -f Procfile.dev
npm ERR! You can get their info via:
npm ERR! npm owner ls react-webpack-rails-tutorial
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! /var/rails/react_on_rails_sample/npm-debug.log
またもや盛大にエラーが出てます。
「sh: foreman: コマンドが見つかりません」と出ているので、foremanがインストールされていないようです。
一応Gemfile.lockを調べてみます。
[root@localhost react_on_rails_sample]# cat Gemfile.lock | grep foreman
インストールされていないですね。。
Gemfileに追加してインストールします。(rails generate react_on_rails:installした時に追加してくれないんですね。。。
開発でしか使わないので、group :development doにでも書いておきましょう。
・・・
group :development do
# Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', '~> 2.0'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'foreman' ←追加
end
・・・
bundle installが完了したら改めてnpm run rails-serverを実行してみましょう。
[root@localhost react_on_rails_sample]# npm run rails-server
> react-webpack-rails-tutorial@1.1.1 rails-server /var/rails/react_on_rails_sample
> echo 'visit http://localhost:3000/hello_world' && foreman start -f Procfile.dev
visit http://localhost:3000/hello_world
sh: foreman: コマンドが見つかりません
・・・
・・・そうでした。。gemをプロジェクトのローカルにインストールしているので通常のforemanコマンドは使えません。bundler execが必要です。
なので、npm runで実行するrails-serverを修正します。
{
"name": "react-webpack-rails-tutorial",
"version": "1.1.1",
・・・
"scripts": {
"postinstall": "cd client && npm install",
"test": "rspec && (cd client && npm run lint)",
"express-server": "echo 'visit http://localhost:4000' && cd client && npm start",
"rails-server": "echo 'visit http://localhost:3000/hello_world' && foreman start -f Procfile.dev"
↓foremanの直前にbundle execを追加
"rails-server": "echo 'visit http://localhost:3000/hello_world' && bundle exec foreman start -f Procfile.dev"
},
・・・
変更後、再度npm run rails-serverを実行します。
[root@localhost react_on_rails_sample]# npm run rails-server
> react-webpack-rails-tutorial@1.1.1 rails-server /var/rails/react_on_rails_sample
> echo 'visit http://localhost:3000/hello_world' && bundle exec foreman start -f Procfile.dev
visit http://localhost:3000/hello_world
23:03:12 web.1 | started with pid 3360
23:03:12 client.1 | started with pid 3361
23:03:12 server.1 | started with pid 3363
23:03:12 client.1 | rm: cannot remove `app/assets/javascripts/generated/*': そのようなファイルやディレクトリはありません
23:03:13 server.1 |
23:03:13 server.1 | > react-webpack-rails-tutorial@1.1.0 build:dev:server /var/rails/react_on_rails_sample/client
23:03:13 server.1 | > webpack -w --config webpack.server.rails.config.js
23:03:13 server.1 |
23:03:13 client.1 |
23:03:13 client.1 | > react-webpack-rails-tutorial@1.1.0 build:dev:client /var/rails/react_on_rails_sample/client
23:03:13 client.1 | > webpack -w --config webpack.client.rails.config.js
23:03:13 client.1 |
23:03:14 client.1 | Webpack dev build for Rails
23:03:17 web.1 | [2016-02-09 23:03:17] INFO WEBrick 1.3.1
23:03:17 web.1 | [2016-02-09 23:03:17] INFO ruby 2.2.2 (2015-04-13) [x86_64-linux]
23:03:17 web.1 | [2016-02-09 23:03:17] INFO WEBrick::HTTPServer#start: pid=3360 port=3000
23:03:23 server.1 | Hash: 8d83dd48f344ad6f63e2
23:03:23 server.1 | Version: webpack 1.12.13
23:03:23 server.1 | Time: 9435ms
23:03:23 server.1 | Asset Size Chunks Chunk Names
23:03:23 server.1 | server-bundle.js 1.84 MB 0 [emitted] main
23:03:23 server.1 | [0] multi main 40 bytes {0} [built]
23:03:23 server.1 | + 649 hidden modules
23:03:27 client.1 | Hash: 9c2e8dbbd6027ec29bd6
23:03:27 client.1 | Version: webpack 1.12.13
23:03:27 client.1 | Time: 13139ms
23:03:27 client.1 | Asset Size Chunks Chunk Names
23:03:27 client.1 | app-bundle.js 4.49 MB 0 [emitted] app
23:03:27 client.1 | vendor-bundle.js 1.54 MB 1 [emitted] vendor
23:03:27 client.1 | [0] multi app 28 bytes {0} [built]
23:03:27 client.1 | [0] multi vendor 76 bytes {1} [built]
23:03:27 client.1 | + 655 hidden modules
【VirtualBoxなど利用している場合】
上記でサーバーの起動まで完了しましたが、今回はVirtualBoxに作った環境にホストOSからアクセスしていたのでもう一手間必要でした。
【変更前】
web: rails s
client: sh -c 'rm app/assets/javascripts/generated/* || true && cd client && npm run build:dev:client'
server: sh -c 'cd client && npm run build:dev:server'
【変更後】
web: rails s -b 0.0.0.0
client: sh -c 'rm app/assets/javascripts/generated/* || true && cd client && npm run build:dev:client'
server: sh -c 'cd client && npm run build:dev:server'
外部からアクセスする場合は、rails sで -b 0.0.0.0を指定する必要があるので、上記のように修正しました。
これで、http://localhost(またはIP):3000/hello_world
にアクセスすると下記のような画面が表示されるようになると思います。
サーバーサイドレンダリング出来ているかは、ブラウザのJavascriptを無効にしてからアクセスするとちゃんと表示されるので、サーバーサイドレンダリングが出来ているのが確認できると思います。