39
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby on RailsAdvent Calendar 2015

Day 8

JavaScript on Node.js X Ruby on Rails

Last updated at Posted at 2015-12-07

JavaScript はWebアプリケーションの特にフロントエンドで大切な存在です。
Rails もWebアプリケーションの開発で便利な機能がたくさんあります。
この2つのメカニズムを使うのに、どちらかによせて混ぜ合わせるのではなく
それぞれに分離して、2つのメカニズムをクロスして使うほうが幸せを感じます。

Ruby on Rails に慣れていない、JavaScript のエンジニア向けに View
ReactRedux を利用した JavaScriptRails をクロスする手順を記します。

このサンプルはGitHubで公開しています。

Environment

  • Ruby: v2.2.3
  • Rails: v4.2.5
  • Node.js: v4.2.1
  • React: v0.14.0
  • Redux: v3.0.4
  • webpack: v1.12.9
  • yo: v1.5.0
  • generator-redux: v0.3.1

Rails new

  • rails new のコマンドでWebアプリケーションが簡単に構築できます。
$ rails new rails-react-example
$ cd ./rails-react-example

Yeoman

  • YeomanGenerator を利用して Redux を構築します。
$ npm install --global yo
$ npm install --global generator-redux
  • Phoenix の様に JavaScript/private/static に設置します。
  • yo redux のコマンドで対話式にWebアプリケーションが構築できます。
  • Rails3000 ポートを標準で利用するので、ここでは 4000 を設定します。
$ mkdir -p ./private/static
$ cd ./private/static
$ yo redux
? What's the name of your application? static
? Describe your application in one sentence: ...
? Which port would you like to run on? 4000
? Install dependencies? No

npm

  • package.json ファイルをルートディレクトリにコピーします。
  • npm install コマンドで JavaScript のライブラリがインストールされます。
$ cd ../../
$ cp ./private/static/package.json .
$ echo /node_modules >> .gitignore
$ npm install
  • package.jsonscripts のコマンドに cd ./private/static && を付加します。
package.json
"scripts": {
  "start": "cd ./private/static && DEBUG=true node server.js",
  "build": "cd ./private/static && webpack -p --config webpack.production.js",
  "build-dev": "cd ./private/static && webpack -p"
},
  • npm start のコマンドを実行すると Node.jswebpack-dev-server (内部はexpress) でWebアプリケーションが起動します。
  • http://localhost:4000/ にアクセスすると Welcome Home! のサンプルが表示されます。

node

view-source:

<html>
<head>
  <meta charset="utf-8">
  <title>Redux/React App</title>
  <link href="./static/app.css" rel="stylesheet" type="text/css" />
</head>
<body>

  <div id="main"></div>

  <script src="./static/bundle.js"></script>
</body>
</html>

これは Redux Generator が出力したサンプルで、Update Title をクリックして入力すると Welcome の隣の文字が変更されます。
redux-devtoolsreact-hot-loader など開発に便利なパッケージがバンドルされています。

まだ Node.js しか使っていないので、次は Rails も使います。


Rails controller

  • rails generate controller コマンドで ReactVirtual DOM を設置する場所を作ります。
$ rails generate controller main index
  • routes.rbRails のWebアプリケーション root を設定します。
config/routes.rb
Rails.application.routes.draw do
  root 'main#index'
end
  • main_helper.rbDevelopment なら先ほどの Node.js のWebアプリケーションを参照するメソッドを準備します。
app/helpers/main_helper.rb
module MainHelper
  def pack_path(path)
    url = ""
    url = "http://localhost:4000/static/" if Rails.env.development?
    url + path
  end
end
  • index.html.erbVirtual DOM が設置される id="main" を準備します。
  • app.cssbundle.jsMainHelperpack_path に設定します。
app/views/main/index.html.erb
<div id="main"></div>
<%= stylesheet_link_tag    pack_path('app.css') %>
<%= javascript_include_tag pack_path('bundle.js') %>
  • webpack.config.jspublicPathMainHelper で指定した URL を追加します。
private/webpack/webpack.config.js
output: {
  path: __dirname + '/static/',
  publicPath: 'http://localhost:4000/static/',
  filename: 'bundle.js',
  hot: true
},

Development

  • RailsNode.js のWebアプリケーションを実行するのに foreman を利用します。
  • Gemfileforeman を追加します。

Gemfile:

$ echo "gem 'foreman', require: false" >> Gemfile
  • ProcfileRailsNode.js のWebアプリケーションの起動コマンドを追加します。

Procfile:

$ echo "web: rails server" >> Procfile
$ echo "pack: npm start" >> Procfile
  • bundle コマンドを Ruby のライブラリをインストールします。
  • foreman start コマンドでWebアプリケーションを起動します。
$ bundle
$ foreman start

http://localhost:3000/ にアクセスすると Redux のサンプルが表示されます。

development

StyleSheetJavaScripthttp://localhost:4000/ を参照しています。

view-source:

<div id="main"></div>
<link rel="stylesheet" media="screen" href="http://localhost:4000/static/app.css" />
<script src="http://localhost:4000/static/bundle.js"></script>

Rails が出力したわずかな ViewVirtual DOMView を足しているので
見た目や、性能は 4000 ポートの Node.js のWebアプリケーションと同じです。
もちろん redux-devtoolsreact-hot-loader が使えるので開発が捗ります。


Production

Production では redux-devtoolsreact-hot-loader は不要なので、webpack でまとめます。

  • Asset Precompileapp.cssbundle.js を追加します。
config/initializers/assets.rb
Rails.application.config.assets.precompile += %w(app.css bundle.js)
  • webpack.production.jsvendor/assets/ に出力されるように編集します。
private/static/webpack.production.js
output: {
  path: __dirname + '../../../vendor/assets/',
  publicPath: '/static/',
  filename: 'javascripts/bundle.js',
},
plugins: [
  new webpack.NoErrorsPlugin(),
  devFlagPlugin,
  new ExtractTextPlugin('stylesheets/app.css')
],
  • npm run build コマンドで app.cssbundle.js が生成されます。
  • rake assets:precompile コマンドを app.cssbundle.jsPrecompile します。
  • rails s -e production コマンドでWebアプリケーションを起動します。
$ echo /public/assets >> .gitignore
$ echo /vendor/assets >> .gitignore
$ npm run build
$ RAILS_ENV=production rake assets:precompile
$ RAILS_SERVE_STATIC_FILES=o SECRET_KEY_BASE=o rails s -e production

http://localhost:3000/ にアクセスすると Redux のサンプルが表示されます。

production

StyleSheetJavaScript/assets/ を参照しています。

view-source:

<div id="main"></div>
<link rel="stylesheet" media="screen" href="/assets/app-5edef2394b419bead200965dfdae792e54801bdd97f057758a8bc0a72f25685d.css" />
<script src="/assets/bundle-66f3247c874d05e4bf42eb08d4fc66d88bd796bdbca894259cd898078a39bf97.js"></script>

これで JavaScript on Node.js X Ruby on Rails の基本の準備ができました。
ViewReact に任せて RailsView にあまり関心を持たないほうがいいですね。


Tips

見た目が寂しなら Material-UIで簡単に装飾できます。

$ npm install material-ui --save
  • RaisedButton でボタンをいい感じに仕上げます。
private/static/js/components/Home.js
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as HomeActions from '../actions/HomeActions';
import styles from '../../css/app.css';
import RaisedButton from 'material-ui/lib/raised-button';

class Home extends Component {
  render() {
    const {title, dispatch} = this.props;
    const actions = bindActionCreators(HomeActions, dispatch);
    return (
      <main>
        <h1 className={styles.text}>Welcome {title}!</h1>
        <RaisedButton label='Update Title' onClick={e => actions.changeTitle(prompt())} />
      </main>
    );
  }
}

export default connect(state => state.Sample)(Home)

material-ui

JavaScript のライブラリの npmRuby のライブラリの Gem に作り替えて使う方法もよいですが
関心事を分離して開発することが幸せと感じます。

Enjoy JavaScript on Node.js X Ruby on Rails

39
35
1

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
39
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?