(2017.01.18追記)Dockerfile.developmentを修正しました。ローカルモードでインストールしたnpmパッケージをshellから実行できるように、パスを追加しました。
はじめに
先日、以下でdocker上に Rails5の開発環境を構築しました。
10ステップでMac OS XにRails5のDocker開発環境を構築する
今度は、上記開発環境にnpm(nodejs)をインストールし、railsから、browserify-rails経由でnpmを利用できるようにします。
そうした上で、npm経由でインストールした、ReactjsとReactjsベースのマテリアルデザインフレームワークmaterial-uiをRailsから利用するところまでやってみようと思います。
マテリアルデザインとは〜基本概念と実務で使える無料フレームワーク6選
material-ui
npm環境構築
ここからは、まず、以下の記事で紹介した手順を完了していることを前提とします
10ステップでMac OS XにRails5のDocker開発環境を構築する
1.Dockerfile
webコンテナのDockerfileを以下のように修正し、nodejs, npmをインストールします。
-
修正点1(9行目から17行目): nvm経由で、nodejsをインストールします。 apt-getでやると指定したバージョンのnodejsがインストールできないので、このようにします。npmはnodejsをインストールすると自動的にインストールされます。
-
修正点2(31行目から32行目): npm のinstallを実行します。26行目にADDしているのは、pakcage.jsonの変更がない場合には実行省略できるようにするためです。
-
修正点3 (2017.01.18追記)(23-24行目)ローカルモードでインストールしたnpmパッケージをshellから実行できるように、パスを追加しました。
FROM ruby:2.3.1
# Replace shell with bash so we can source files
#RUN rm /bin/sh && ln -sf /bin/bash /bin/sh
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 7.2.0
# Install nvm with node and npm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.30.1/install.sh | bash \
&& . $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm alias default $NODE_VERSION \
&& nvm use default
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
# ARG命令でdocker-compose.ymlから渡されたAPP_HOMEという引数を参照できるようにします
ARG APP_HOME
ENV PATH $APP_HOME/node_modules:$PATH
ENV PATH $APP_HOME/node_modules/.bin:$PATH
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
ADD Gemfile $APP_HOME/
ADD Gemfile.lock $APP_HOME/
RUN bundle install -j4
ADD package.json $APP_HOME/
RUN npm install
ADD . $APP_HOME
2.package.jsonの追加
package.jsonをprojectルートに追加し、必要なパッケージをインストールします。
reactjs用、material-uiのパッケージもインストールします。
$ docker-compose run --rm web init npm
$ docker-compose run --rm web npm install --save-dev browserify
$ docker-compose run --rm web npm install --save-dev babelify
$ docker-compose run --rm web npm install --save-dev browserify-incremental
$ docker-compose run --rm web npm install --save-dev react
$ docker-compose run --rm web npm install --save-dev react-dom
$ docker-compose run --rm web npm install --save-dev react-tap-event-plugin
$ docker-compose run --rm web npm install --save-dev material-ui
3.Gemfileにbrowserify-railsの追加
gem "browserify-rails"
bundle install実行
$ docker-compose run --rm web bundle install
browserify_railsの設定を追加します。
config.browserify_rails.commandline_options = "-t babelify"
config.less.paths << "#{Rails.root}/node_modules/material-ui/src/less/"
config.browserify_rails.use_browserifyinc = true
4.まずここでいったんビルド
ここでまずビルドしてイメージ作成後コンテナを実行してみます。
localhost:3000に接続して、今まで通り表示されればOK
$ docker-compose build
$ docker-compose up
Reactjs + material-uiのサンプルコード
react部分についてはgemのreact-railsを使う記事が多いですが、material-uiとうまくつなげることができなかったのとフロントのパッケージはnpmで管理しようということで、今回は使いません。
サンプルコードとしては、以下のようにRaisedButtonを表示するものを作ります!!!!
コンポーネント作成
import React from 'react';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import RaisedButton from 'material-ui/RaisedButton';
import {pinkA100} from 'material-ui/styles/colors';
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
const style = {
margin: 12,
};
class Feeling extends React.Component {
constructor(props) {
super(props)
}
render () {
return (
<RaisedButton key={this.props.id} style={style} secondary={true} label={this.props.name} />
)
}
}
export default class Feelings extends React.Component {
constructor(props) {
super(props)
this.state = {feelings: [{id: 1, name: '喜'}, {id: 2, name: '怒'}, {id: 3, name: '哀'}, {id: 4, name: '楽'}]}
}
render () {
return (
<MuiThemeProvider muiTheme={getMuiTheme()}>
<div className='messages'>
{this.state.feelings.map(function (feeling, i) {
return <Feeling key={i} id={feeling.id} name={feeling.name}/>
})}
</div>
</MuiThemeProvider>
)
}
}
import React from 'react';
import ReactDOM from 'react-dom';
import Feelings from './components/feelings';
import injectTapEventPlugin from 'react-tap-event-plugin';
// Needed for React Developer Tools
window.React = React;
injectTapEventPlugin();
ReactDOM.render(<Feelings />, document.getElementById('feelings'));
以下のように、コンポーネントの生成は、HTMLがすべてロードされてからやる必要があります。
(gemのreact_railsを利用するとこの辺はいいようにできるのですが....)
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
$(function(){
// DOM がロードされてから
require('./components');
});
top_controller 作成
$ docker-compose run --rm web bundle exec rails g controller top
ルーティングを設定します。
Rails.application.routes.draw do
root to: 'top#index'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
$ docker-compose build
$ docker-compose up
material-ui の使い方は随時整理していきます。