Rails
Node.js
React
hypernova

rails, react, hypernovaの環境構築からのHello World!

概要

rails、nodejs環境をVMに構築して、サーバサイドレンダリング用ライブラリであるHypernovaの環境構築から、Hello worldまでをメモ。

環境・バージョン

  • Amazon linux2 (vagrant)
  • Vagrantfileを編集(下記をそれぞれ追記)
    • config.vm.network "forwarded_port", guest: 3000, host: 3000
    • config.vm.network "private_network", ip: "192.168.33.10"
    • config.vm.synced_folder ".", "/Vagrant"
  • OS設定まわりを少し
    • UTC→JST
    • vagrantユーザ以外の個人ユーザを作成
    • timezone変更
    • hostname変更
    • export LANG=ja_JP.UTF-8 を.bash_profileに追記
    • yum install gcc-c++ openssl-devel git readline-devel sqlite-devel -y
    • yum update
    • rbenv、nvmインストール
  • ruby, nodejsインストール
# ruby/rails(rbenv)
$ rbenv -v
rbenv 1.1.1-28-gb943955
$ ruby -v
ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux]
$ gem -v
2.6.13
$ rails -v
Rails 5.1.4

# node/npm(nvm)
$ nvm --version
0.33.8
$ node -v
v7.9.0
$ npm -v
4.2.0

1. Railsアプリの作成

rails newでアプリを作成します。

$ rails new hypernova-getting-started-with-rails

2. Controllerの作成

/welcome/indexで動作するcontrollerを作成します。

$ rails generate controller welcome index

3. browserify-railsの導入

Gemfile に以下の一行を追加してbundle installを行います。

Gemfile
gem "browserify-rails"
$ bundle install
Installing browserify-rails 4.2.0

4. JavaScriptの環境設定 (package.json)

以下のコマンドでpackage.jsonを作成し、必要なパッケージ情報などを追記します。

% npm init -y
package.json
{
  "name": "hypernova-getting-started-with-rails",
  "private": true,
  "dependencies": {
    "hypernova": "^1.0.0",
    "hypernova-react": "^1.0.0",
    "react": "^15.1.0",
    "react-dom": "^15.1.0"
  },
  "devDependencies": {
    "browserify": "^13.0.1",
    "browserify-incremental": "^3.1.1"
  },
  "description": "This README would normally document whatever steps are necessary to get the application up and running.",
  "version": "1.0.0",
  "main": "index.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "fk2000",
  "license": "MIT"
}

package.jsonが用意できたら以下のコマンドを実行しJavaScriptのパッケージをインストールします。

% npm install

5. Hypernova/serverの設定

Rails.rootディレクトリにhypernova.jsを作ります。

hypernova.js
const hypernova = require('hypernova/server');

hypernova({
  devMode: true,

  getComponent(name) {
    if (name === 'MyComponent.js') {
      return require('./app/assets/javascripts/MyComponent.js');
    }
    return null;
  },

  port: 3030,
});

6. Hypernova/rubyの設定

Gemfileにhypernovaを追加することで、Ruby(Rails)用のHypernovaクライアントを読み込みます。

Gemfileに以下1行を追加し、bundle installを実行してインストールします。

Gemfile
gem "hypernova"

続いて、Railsアプリから先ほどのhypernova.jsに記述したHypernova/serverへアクセスするための設定を追加します。

#{Rails.root}/config/initializers/hypernova.rbとして以下を作成します。

config/initializers/hypernova.rb
require 'hypernova'

Hypernova.configure do |config|
  config.host = 'localhost'
  config.port = 3030
end

config.portにはhypernova.jsに記載したポート番号「3030」と一致させます。

7. Hypernova/reactを使用したReactコンポーネント

props.nameを受け取って表示し、クリックするとアラートを表示するだけのシンプルなReactコンポーネントを作成します。ファイルは#{Rails.root}/app/assets/javascripts/MyComponent.jsというファイル名としています。

app/assets/javascripts/MyComponent.js
var React = require('react');
var renderReact = require('hypernova-react').renderReact;

function MyComponent(props) {
  return React.createElement('div', {
    onClick: function () {
      alert('Click handlers work.');
    },
  }, 'Hello, ' + props.name + '!');
}

module.exports = renderReact('MyComponent.js', MyComponent);

8. RailsアプリからHypernova呼び出し

Hypernova/rubyは2つのmethodを提供します。Hypernovaによるサーバサイドレンダリングをサポートするaround_filterhypernova_render_supportと、Reactコンポーネントをpropsを指定してViewに読み込むrender_react_componentです。

以下のように、使用するControllerとViewで以下のように呼び出します。

app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
  around_filter :hypernova_render_support
  def index
  end
end
app/views/welcome/index.html.erb
<%= render_react_component('MyComponent.js', name: 'World') %>

さらに、Viewで読み込むJavaScriptファイルを指定するために、app/views/layouts/application.html.erbを修正します。javascript_include_tagの位置を<head>内から</body>の直前へ移動しています。

app/views/layouts/application.html.erb
 <!DOCTYPE html>
 <html>
   <head>
     <title>HypernovaGettingStartedWithRails</title>
     <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
-    <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
     <%= csrf_meta_tags %>
   </head>
   <body>

   <%= yield %>

+  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
   </body>
 </html>

9. 動作を確認してみる

Railsアプリを起動します。

% bin/rails server

起動したら、ブラウザで http://localhost:3000/welcome/index へアクセスします。

ところが、下記のように表示されます。
screenshot-127.0.0.1-3000-2018-01-25-14-39-04-560.png

※参考にした記事ではwelcome_controller.rbに追加したメソッド名は「around_filter」となっていましたが、「undefined method `around_filter'」となり、「Did you mean? around_action」と出力されてたので下記のように変更しました。

変更後のapp/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
- around_filter :hypernova_render_support
+ around_action :hypernova_render_support
  def index
  end
end

再度、rails s でrailsを再起動し、ブラウザを確認すると、Hello, World!と表示され、文字をクリックするとブラウザアラートボックスが表示されることが確認できます。

20180125_rails_hypernova.png

ページのソースを確認してみると、該当部分は以下のようになっていると思います。

<div data-hypernova-key="MyComponentjs"></div>
<script type="application/json" data-hypernova-key="MyComponentjs"><!--{"name":"Hypernova"}--></script>

これは、 サーバサイドレンダリングを利用していない のですが、正しくアプリは動作しています。

サーバサイドレンダリング編へつづく。

参考URL

https://qiita.com/noriaki/items/e2dac69b9dd88334dd43