Edited at

【動画付き】Rails 5.1で作るVue.jsアプリケーション ~Herokuデプロイからシステムテストまで~

More than 1 year has passed since last update.


はじめに

Rails 5.1ではJavaScript/index.html.erb周りのサポートが大きく改善されました。

これにより、Vue.jsやReactといったモダンなJSフレームワークをRails内で非常に扱いやすくなっています。

僕も実際に試してみましたが、本当にびっくりするぐらい簡単にVue.jsやReactを動かすことができました。

そこでこの記事ではRails 5.1とVue.jsを組み合わせたサンプルアプリケーションの作成方法をチュートリアル形式で、できるだけ詳しく説明します。

また、ローカルで動かしておしまい、ではなく、Herokuにデプロイしたり、テストコードを書いたりするところまでカバーします。

この記事自体は長いですが、実際に手を動かすと(スムーズに進んだ場合)30分以内で終わらせることができるはずです!


今回作成するサンプルアプリケーション

今回は以下のリンク先にあるVue.jsのアプリケーションをRails上で作成します。

http://jsfiddle.net/yyx990803/23qze30k/

このサンプルアプリケーションではテーブルのソートや、データの絞り込みがVue.jsの機能を使って実装されています。

647Lxuyt8h.gif


この記事の解説動画

この記事の内容はYouTubeでも解説しています。

実際にコードを書いたり、画面を動かしたりする様子が動画で確認できるので、さらに内容が理解しやすくなるはずです。

https://www.youtube.com/watch?v=ycOeM2umXkYScreen Shot 2017-02-27 at 10.12.55.png

ちなみに、動画の長さは約40分です。

1.5倍速~2倍速ぐらいで再生すると、サクサクっと視聴できると思います。


この記事で作成したコード

この記事で作成したコードはGitHubにアップしてあります。

コミットログを追いかけていくと、どこで何が変わったのか把握しやすくなると思います。

こちらも参考にしてください。

https://github.com/JunichiIto/rails-vue-sandbox

それでは以下が本編です!


Rubyバージョンの確認

この記事ではRuby 2.4.0を使います。

$ ruby -v

ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin16]

ですが、おそらくRuby 2.2.2以上なら動作するはずです。


Railsバージョンの確認

この記事ではRails 5.1.0.beta1を使います。

(なので、正式リリース時には多少仕様が変わる可能性があります)

$ rails -v

Rails 5.1.0.beta1

なお、gem install rails -v 5.1.0.beta1でインストールできない場合は、以下のコマンドを試してみてください。

$ ruby -rbundler/inline -e "gemfile(true) do; source 'https://rubygems.org/'; gem 'rails', '5.1.0.beta1'; end"

参考:Installing pre release gems is giving conflicting dependency errors · Issue #1653 · rubygems/rubygems


新規Railsアプリを作成する

Rails 5.1でVue.jsを使う場合、3通りの方法があります。



  1. rails new--webpack=vueオプションを付けて、プロジェクトの作成時にVue.jsもインストールする


  2. rails new--webpackオプションを付ける。その後、Vue.jsをインストールする

  3. 普通にrails newして、それからWebpackerとVue.jsをインストールする

一番手軽なのは1の方法ですが、このチュートリアルではWebpackerやVue.jsのインストール時にどこが変わるのか確認するため、あえて3の方法で進めます。

というわけで、以下のコマンドを実行してRailsアプリを作成してください。

$ rails new rails-vue-sandbox


Commitログ

Initial commit · JunichiIto/rails-vue-sandbox@281aa22


Webpacker gemのインストール

続いて、Webpacker gemをインストールします。

Gemfileに以下の行を追加し、bundle installしてください。


Gemfile

gem 'webpacker', github: 'rails/webpacker'


それからbin/rails webpacker:installというコマンドを実行するのですが、その前にまず、Yarnがインストールされていることを確認してください。

$ yarn -v

yarn install v0.20.3
[1/4] 🔍 Resolving packages...
success Already up-to-date.
✨ Done in 0.42s.

インストールされていなければ、以下のページを参考にしてインストールしておきましょう。

Installation | Yarn

Yarnのインストールが済んだら、bin/rails webpacker:installを実行します。

$ bin/rails webpacker:install

これでWebpack関連のファイルや設定が追加されます。

新規追加


  • app/javascript/packs/application.js

  • bin/webpack

  • bin/webpack-dev-server

  • bin/webpack-watcher

  • config/webpack/development.js

  • config/webpack/production.js

  • config/webpack/shared.js

  • yarn.lock

変更


  • .gitignore

  • config/environments/development.rb

  • config/environments/production.rb

  • package.json


Commitログ

Install webpacker · JunichiIto/rails-vue-sandbox@b4b6a58


Vue.jsのインストール

今度はVue.jsのインストールです。

Webpackerをインストールしていれば、コマンド一発でVue.jsがインストールできます。

$ rails webpacker:install:vue

これでVue.js用のファイルや設定が追加されます。

新規追加


  • app/javascript/packs/app.vue


app/javascript/packs/app.vue

<template>

<div id="app">
Hello Vue!
</div>
</template>


  • app/javascript/packs/hello_vue.js


app/javascript/packs/hello_vue.js

// Run this example by adding <%= javascript_pack_tag 'hello_vue' %> to the head of your layout file,

// like app/views/layouts/application.html.erb.
// All it does is render <div>Hello Vue</div> at the bottom of the page.

import Vue from 'vue'
import App from './app.vue'

document.body.appendChild(document.createElement('hello'))

new Vue({
el: 'hello',
template: '<App/>',
components: { App }
})


変更


  • config/webpack/shared.js

  • package.json

  • yarn.lock


hello_vue.jsを表示する画面を作成する

次に、hello_vue.jsを表示する画面を作成します。

まず、コントローラを作成します。

$ rails g controller Home index

コントローラの中身はそのままでOKです。


app/controllers/home_controller.rb

class HomeController < ApplicationController

def index
end
end

Viewは空っぽにしておきます。


app/views/home/index.html.erb



app/views/layouts/application.html.erbには<%= javascript_pack_tag 'hello_vue' %>を追加します。


app/views/layouts/application.html.erb

 <!DOCTYPE html>

<html>
<head>
<title>RailsVueSandbox</title>
<%= csrf_meta_tags %>

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>

<body>
<%= yield %>
+ <%= javascript_pack_tag 'hello_vue' %>
</body>
</html>


routes.rbでは、home#indexをrootページに指定します。


config/routes.rb

Rails.application.routes.draw do

root to: 'home#index'
end


JSのコンパイル

次に、Vue.js関連のJavaScriptをコンパイルします。

JSのコンパイルにはbin/webpackを使います。

ただし、2017年2月27日時点では、このコマンドを実行するとエラーが出ます。

$ bin/webpack

(node:41610) DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic, see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
Hash: c4d67f31e483f6e6e58e
Version: webpack 2.2.1
Time: 752ms
Asset Size Chunks Chunk Names
hello_vue.js 232 kB 0 [emitted] hello_vue
application.js 3.37 kB 1 [emitted] application
hello_vue.js.map 285 kB 0 [emitted] hello_vue
application.js.map 3.33 kB 1 [emitted] application
[0] ./app/javascript/packs/app.vue 2.05 kB {0} [built] [failed] [1 error]
[1] ./~/vue/dist/vue.common.js 226 kB {0} [built]
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] ./app/javascript/packs/application.js 489 bytes {1} [built]
[4] ./app/javascript/packs/hello_vue.js 415 bytes {0} [built]

ERROR in ./app/javascript/packs/app.vue
Module build failed: Error:

Vue packages version mismatch:

- vue@2.1.10
- vue-template-compiler@2.2.1

This may cause things to work incorrectly. Make sure to use the same version for both.
If you are using vue-loader@>=10.0, simply update vue-template-compiler.
If you are using vue-loader@<10.0 or vueify, re-installing vue-loader/vueify should bump vue-template-compiler to the latest.

at Object.<anonymous> (/Users/jit/dev/sandbox/rails-vue-sandbox-2/node_modules/vue-template-compiler/index.js:8:9)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/Users/jit/dev/sandbox/rails-vue-sandbox-2/node_modules/vue-loader/lib/parser.js:1:78)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/Users/jit/dev/sandbox/rails-vue-sandbox-2/node_modules/vue-loader/lib/loader.js:2:13)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/Users/jit/dev/sandbox/rails-vue-sandbox-2/node_modules/vue-loader/index.js:1:80)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)

このエラーを解消するために、yarn upgrade vueでVue.jsのバージョンを上げてください。

$ yarn upgrade vue

yarn upgrade v0.20.3
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning "url-loader@0.5.8" has unmet peer dependency "file-loader@*".
[4/4] 📃 Building fresh packages...
success Saved 1 new dependency.
└─ vue@2.2.1
✨ Done in 4.36s.

こうすると、bin/webpackの実行に成功するはずです。

$ bin/webpack

bin/webpack
(node:60134) DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic, see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
Hash: 5324517c32736f3529f8
Version: webpack 2.2.1
Time: 1043ms
Asset Size Chunks Chunk Names
hello_vue.js 249 kB 0 [emitted] hello_vue
application.js 3.37 kB 1 [emitted] application
hello_vue.js.map 309 kB 0 [emitted] hello_vue
application.js.map 3.33 kB 1 [emitted] application
[0] ./app/javascript/packs/app.vue 1.21 kB {0} [built]
[1] ./~/vue/dist/vue.common.js 242 kB {0} [built]
[2] ./~/vue-loader/lib/component-normalizer.js 1.15 kB {0} [built]
[3] ./~/vue-loader/lib/template-compiler.js?{"id":"data-v-20bbc081"}!./~/vue-loader/lib/selector.js?type=template&index=0!./app/javascript/packs/app.vue 407 bytes {0} [built]
[4] (webpack)/buildin/global.js 509 bytes {0} [built]
[5] ./app/javascript/packs/application.js 489 bytes {1} [built]
[6] ./app/javascript/packs/hello_vue.js 415 bytes {0} [built]


hello_vue.jsの動作確認

それではrails serverを起動しましょう。

$ rails s

http://localhost:3000 にアクセスして、次のような画面が表示されればOKです。

(Rails上でVue.jsが実行できました。おめでとうございます!:tada:

Screen Shot 2017-02-27 at 9.07.19.png


Commitログ

Create home#index · JunichiIto/rails-vue-sandbox@470fc67


Vue.jsサンプルアプリケーションの作成

さて、Vue.jsが動作する環境が整ったので、サンプルアプリケーションを作成に移りましょう。

今回はこちらのページにあるコードを使わせてもらいます。

http://jsfiddle.net/yyx990803/23qze30k/

View、JS、CSSをそれぞれ次のように書き換えてください。


app/views/home/index.html.erb

<!-- component template -->

<script type="text/x-template" id="grid-template">
<table>
<thead>
<tr>
<th v-for="key in columns"
@click="sortBy(key)"
:class="{ active: sortKey == key }">
{{ key | capitalize }}
<span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'">
</span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="entry in filteredData">
<td v-for="key in columns">
{{entry[key]}}
</td>
</tr>
</tbody>
</table>
</script>

<!-- demo root element -->
<div id="demo">
<form id="search">
Search <input name="query" v-model="searchQuery">
</form>
<demo-grid
:data="gridData"
:columns="gridColumns"
:filter-key="searchQuery">
</demo-grid>
</div>



app/javascript/packs/hello_vue.js

import Vue from 'vue'

import App from './app.vue'

// register the grid component
Vue.component('demo-grid', {
template: '#grid-template',
replace: true,
props: {
data: Array,
columns: Array,
filterKey: String
},
data: function () {
var sortOrders = {}
this.columns.forEach(function (key) {
sortOrders[key] = 1
})
return {
sortKey: '',
sortOrders: sortOrders
}
},
computed: {
filteredData: function () {
var sortKey = this.sortKey
var filterKey = this.filterKey && this.filterKey.toLowerCase()
var order = this.sortOrders[sortKey] || 1
var data = this.data
if (filterKey) {
data = data.filter(function (row) {
return Object.keys(row).some(function (key) {
return String(row[key]).toLowerCase().indexOf(filterKey) > -1
})
})
}
if (sortKey) {
data = data.slice().sort(function (a, b) {
a = a[sortKey]
b = b[sortKey]
return (a === b ? 0 : a > b ? 1 : -1) * order
})
}
return data
}
},
filters: {
capitalize: function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
},
methods: {
sortBy: function (key) {
this.sortKey = key
this.sortOrders[key] = this.sortOrders[key] * -1
}
}
})

// bootstrap the demo
var demo = new Vue({
el: '#demo',
data: {
searchQuery: '',
gridColumns: ['name', 'power'],
gridData: [
{ name: 'Chuck Norris', power: Infinity },
{ name: 'Bruce Lee', power: 9000 },
{ name: 'Jackie Chan', power: 7000 },
{ name: 'Jet Li', power: 8000 }
]
}
})



app/assets/stylesheets/home.scss

body {

font-family: Helvetica Neue, Arial, sans-serif;
font-size: 14px;
color: #444;
}

table {
border: 2px solid #42b983;
border-radius: 3px;
background-color: #fff;
}

th {
background-color: #42b983;
color: rgba(255,255,255,0.66);
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

td {
background-color: #f9f9f9;
}

th, td {
min-width: 120px;
padding: 10px 20px;
}

th.active {
color: #fff;
}

th.active .arrow {
opacity: 1;
}

.arrow {
display: inline-block;
vertical-align: middle;
width: 0;
height: 0;
margin-left: 5px;
opacity: 0.66;
}

.arrow.asc {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 4px solid #fff;
}

.arrow.dsc {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid #fff;
}


これらのコードを組み込んだら、JSをコンパイルします。

$ bin/webpack

そしてブラウザをリロードすると、jsfiddleで表示されていた画面と同じ画面が表示されるはずです。

ソートや検索も動作することを確認しておきましょう。

647Lxuyt8h.gif


Commitログ

Create sample app · JunichiIto/rails-vue-sandbox@a46704f


Herokuへのデプロイ

ローカルで動かしておしまい、ではなく、本番環境でも使えるようにしましょう。

今回はHerokuにデプロイしてみます。

(HerokuのアカウントやCLIツールは事前にセットアップしておいてください)


コードの変更

まず、Gemfileを変更します。変更箇所は以下の3点です。


  • Rubyのバージョンを指定する

  • pg gemをインストールする

  • sqlite3 gemを:development, :testグループに移動させる


Gemfile

 source 'https://rubygems.org'

+ruby '2.4.0'
+
git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
"https://github.com/#{repo_name}.git"
@@ -8,8 +10,7 @@ end

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.1.0.beta1'
-# Use sqlite3 as the database for Active Record
-gem 'sqlite3'
+gem 'pg'
# Use Puma as the app server
gem 'puma', '~> 3.7'
# Use SCSS for stylesheets
@@ -35,6 +36,7 @@ gem 'jbuilder', '~> 2.5'
# gem 'capistrano-rails', group: :development

group :development, :test do
+ gem 'sqlite3'
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
# Adds support for Capybara system testing and selenium driver


Gemfileを変更したらbundle installを実行します。

続いて、プロジェクトのルートディレクトリにProcfileを作成します。


Procfile

web: bundle exec puma -p $PORT



Commitログ

Setup for Heroku · JunichiIto/rails-vue-sandbox@8c1827d


Herokuインスタンスの作成とデプロイ

Herokuへのデプロイは次のようにコマンドを入力していってください。

# インスタンスの作成

$ heroku create

# add-onの追加
$ 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上のアプリケーションを開く
$ heroku open

通常のデプロイと変わっている点はビルドパックを追加するところです。

これを追加しないと、デプロイ時にエラーが発生します。

参考:Introducing Webpacker – Statuscode – Medium

Heroku上のアプリケーションを開いたときに、ローカルと同じように動作すればOKです!

JjdabqGftj.gif


webpack-dev-serverを有効にする

さて、今のままだと、Vue.js用のJSを変更するたびに毎回bin/webpackを実行しなければいけません。

これはちょっと面倒なので、webpack-dev-serverという機能を利用して、JSを変更したらすぐに変更が反映されるようにしましょう。

まず、ルートディレクトリにProcfile.devというファイルを作成します。


Procfile.dev

web: bundle exec rails s

# watcher: ./bin/webpack-watcher
hot: ./bin/webpack-dev-server

それから、binディレクトリの下にserverという名前のファイルを作成します。


bin/server

#!/bin/bash -i

bundle install
bundle exec foreman start -f Procfile.dev

serverは実行可能なファイルにしておきます。

$ chmod 777 bin/server

また、serverではforemanを使うので、Gemfileに追加してbundle installします。


Gemfile

 group :development do

# ...
+ gem 'foreman'
end

最後に、config/environments/development.rbにある、config.x.webpacker[:dev_server_host] = "http://localhost:8080"のコメントを外します。


config/environments/development.rb

 Rails.application.configure do

# Make javascript_pack_tag load assets from webpack-dev-server.
- # config.x.webpacker[:dev_server_host] = "http://localhost:8080"
+ config.x.webpacker[:dev_server_host] = "http://localhost:8080"

rails sでサーバーを起動していたら停止し、bin/serverでサーバーを起動してください。

サーバーが起動したら http://localhost:5000/ にアクセスします。

こうすると、hello_vue.jsへの変更が、即座に画面に反映されるようになります。

YLZV9SLrYZ.gif


Commitログ

Setup for webpack-dev-server · JunichiIto/rails-vue-sandbox@07d8a79


Vue.js用のシステムテストを書く

最後に、この画面のテストコードも書いておきましょう。

Rails 5.1ではSystemTestCaseという新しいテストケースクラスが導入されました。

これを使うと、JavaScriptを利用する画面のテストが書けます。

SystemTestCaseではChromeDriverというドライバを使います。

これは事前にセットアップが必要です。

以下の記事を参考にしてセットアップしてください。

Rails 5.1のSystemTestCaseを試してみた - Qiita

ChromeDriverをセットアップしたら、テストコードを作成します。

今回はtest/system/home_test.rbというファイルを作成します。


test/system/home_test.rb

require "application_system_test_case"

class HomeTest < ApplicationSystemTestCase
test "visiting the index" do
# トップページを開く
visit root_path

# 4人とも表示される
assert_text 'Chuck Norris'
assert_text 'Bruce Lee'
assert_text 'Jackie Chan'
assert_text 'Jet Li'

# "J"でフィルタリングする(2人表示)
fill_in 'query', with: 'J'
assert_no_text 'Chuck Norris'
assert_no_text 'Bruce Lee'
assert_text 'Jackie Chan'
assert_text 'Jet Li'

# "Jet"でフィルタリングする(1人だけ表示)
fill_in 'query', with: 'Jet'
assert_no_text 'Chuck Norris'
assert_no_text 'Bruce Lee'
assert_no_text 'Jackie Chan'
assert_text 'Jet Li'
end
end


なお、コントローラのテストは使わないので中身を消しておきます。


test/controllers/home_controller_test.rb

require 'test_helper'

class HomeControllerTest < ActionDispatch::IntegrationTest
# 削除
end


テストコードが書けたら、テストを実行します。

$ rake

Run options: --seed 19056

# Running:

Puma starting in single mode...
* Version 3.7.1 (ruby 2.4.0-p0), codename: Snowy Sagebrush
* Min threads: 0, max threads: 1
* Environment: test
* Listening on tcp://0.0.0.0:64816
Use Ctrl-C to stop
.

Finished in 3.184606s, 0.3140 runs/s, 0.0000 assertions/s.

1 runs, 0 assertions, 0 failures, 0 errors, 0 skips

このようにすると、モダンなJavaScriptフレームワークを使っている場合でもちゃんとテストを書くことができます。


Commitログ

Test for home#index · JunichiIto/rails-vue-sandbox@caebff1


応用:Vue.jsではなくReactやAngularを使う

今回はVue.jsを使いましたが、ReactやAngular(+TypeScript)を使う場合も基本的な流れは同じです。

rails webpacker:install:vueの代わりに、rails webpacker:install:reactrails webpacker:install:angularを実行するとReactやAngular用のセットアップが完了します。

詳しくはWebpacker gemのREADMEをご覧ください。

https://github.com/rails/webpacker


参考:おおまかなディレクトリ&ファイル構成

今回のVue.jsアプリケーションに関連しそうなディレクトリとファイルだけを、独断でピックアップしてtree表示してみました。

各ファイルはこんな感じで配置されています。

.

├── app
│   └── javascript
│      └── packs
│      ├── app.vue
│      ├── application.js
│      └── hello_vue.js
├── bin
│   ├── webpack
│   ├── webpack-dev-server
│   ├── webpack-watcher
│   └── yarn
├── config
│   └── webpack
│   ├── development.js
│   ├── production.js
│   └── shared.js
├── node_modules
│   └── vue
├── package.json
├── public
│   └── packs
│      ├── application.js
│      ├── application.js.map
│      ├── hello_vue.js
│      └── hello_vue.js.map
└── yarn.lock


まとめ

というわけで、この記事ではRails 5.1でVue.jsのサンプルアプリケーションを作成する手順を説明しました。

これまではモダンなJavaScriptフレームワークに対して「いっぱいツールがあって、スタートラインに立つまでが大変」という印象を持っていました。

しかし、Rails 5.1を使うとあっという間にVue.jsやReactの開発環境を構築することができました。

これはとてもすごいことだと思います。

もちろん、ここで作成したのはHello, worldレベルのサンプルアプリケーションの作成です。

実務で使うためにはもっといろんな知識が必要になるはずです。

とはいえ、「とりあえず動かして試せる環境」があるのとないのでは大違いです。

動かせる環境があれば、「何をどうすればどう変わるのか」が理解しやすくなるので、漠然と技術記事を眺めるよりもぐんと学習効率がアップすると思います。

この記事を参考にして、みなさんもぜひ手元でモダンなJSフレームワーク環境を構築してみてください!


あわせて読みたい

僕が書いたRails 5.1関連のQiita記事です。

こちらもあわせてどうぞ。


Special thanks

Rails 5.1で導入されたJSの新機能については、以下の記事を参考にさせてもらいました。

どうもありがとうございました。