Webpackerを使ったRailsの新しいフロントエンド環境に慣れておくために、Riot.jsを導入し、ES6のコードをbabelでトランスコンパイルしてブラウザで動かすサンプルを作ってみます。
本番環境にデプロイすることも想定し、最終的にHerokuで動かすところまでやってみます。
この記事ではRiot.jsを使います。お間違いのないように。。
1. rails new
まずはいつものようにRailsを初期化。--webpack
オプションでWebpacker付きでインストールされる。
$ mkdir rails5.1-riot-example; cd $_
$ bundle init
Gemfileを編集して railsを有効化
gem "rails"
$ bundle exec rails new . --webpack
gemのインストール後にwebpacker:install
タスクが自動的に実行され、babel
やwebpack
などのNode.jsモジュールがyarn
経由でインストールされる。
自動生成されるpackage.json
は以下のようになっていた。
{
"name": "rails5_1-riot-example",
"private": true,
"dependencies": {
"autoprefixer": "^7.1.1",
"babel-core": "^6.24.1",
"babel-loader": "7.x",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.5.1",
"coffee-loader": "^0.7.3",
"coffee-script": "^1.12.6",
"compression-webpack-plugin": "^0.4.0",
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.11.1",
"glob": "^7.1.2",
"js-yaml": "^3.8.4",
"node-sass": "^4.5.3",
"path-complete-extname": "^0.1.0",
"postcss-loader": "^2.0.5",
"postcss-smart-import": "^0.7.4",
"precss": "^1.4.0",
"rails-erb-loader": "^5.0.1",
"resolve-url-loader": "^2.0.2",
"sass-loader": "^6.0.5",
"style-loader": "^0.18.1",
"webpack": "^2.6.1",
"webpack-manifest-plugin": "^1.1.0",
"webpack-merge": "^4.1.0"
},
"devDependencies": {
"webpack-dev-server": "^2.4.5"
}
}
2. 空っぽのページを作る
Rails.application.routes.draw do
root 'application#index'
end
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def index
end
end
レイアウトからSprocketsのヘルパー (stylesheet_link_tag
とjavascript_include_tag
) を消し、代わりにjavascript_pack_tag
を追加する。
<%= javascript_pack_tag 'application' %>
とした場合、public/packs/application.js
javascript_pack_tag
が示すJavaScriptファイルは後ほど作成する。
<!DOCTYPE html>
<html>
<head>
<title>Rails51RiotExample</title>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
<%= javascript_pack_tag 'application' %>
</body>
</html>
3. Riotを使う為の環境設定
パッケージの名称に注意 (Riot本体はriot、loaderはriotjs-loader)。
npm install
とは違い、yarn add
はオプション無しでpackage.json
が更新される。
$ bin/yarn add riot riotjs-loader
tagファイルをriotjs-loaderに投げる設定
module.exports = {
test: /\.tag$/,
loader: 'babel-loader!riotjs-loader'
}
グローバルでriotを参照できるようにする。
// ---
plugins: [
new webpack.ProvidePlugin({riot: 'riot'}), // 追加
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
// ---
4. JavaScriptを用意
起点になるJavaScriptファイルを作成
const riot = require('riot')
require('../tags/app.tag')
document.addEventListener('DOMContentLoaded', () => {
document.body.appendChild(document.createElement('app'))
riot.mount('*')
})
Riot.jsのカスタムタグを作成
(1秒ごとに時刻を更新するだけのアプリ)
<app>
<div>
<p>Hello world</p>
<p>
<strong>{time}</strong>
</p>
</div>
<script>
this.on('mount', () => {
setInterval(this.updateTime, 1000)
})
updateTime() {
this.update({time: Date()})
}
</script>
</app>
5. 動作確認
webpack-dev-serverを起動すると、変更を検知して自動でトランスパイルしてくれる。
$ bin/webpack-dev-server
別端末でrailsを起動しhttp://localhost:3000/
で動作確認ができる。
6. Herokuで動かす
Gemfile
にPostgreSQL用のgemを追加しておく。
# ---
gem 'pg', group: :production
gem 'sqlite3', group: [:development, :test]
# ---
heroku上にアプリケーションを作成する。
WebpackでトランスコンパイルするためにNode.jsのビルドパックを追加する必要がある。Rubyのビルドパックも明示的に追加しておく。
$ heroku create
$ heroku addons:create heroku-postgresql:hobby-dev
# ビルドパックの追加
$ heroku buildpacks:add --index 1 heroku/nodejs
$ heroku buildpacks:add --index 2 heroku/ruby
# デプロイ
$ git push heroku master
$ heroku run rake db:migrate
# アプリケーションを開く
$ heroku open
production用としてちゃんとUglifyされている。
超かんたん!
まとめ
フロントエンドと聞くと、npmやらbowerやらyoemanやらgruntやらgulpやら、環境構築が辛いイメージがありましたが、今回は設定ファイルをほぼ触らずに簡単にデプロイできたので驚きました。
片手間でテキトーにJS書いているような自分にはちょうどよい感じですね!(・∀・)