Railsにこれから初めて触れる方を対象にしたチュートリアルです RailsとVue.jsを使ってSPA(シングルページアプリケーション)のサンプルを作成します
まず、rails newを実行し、Railsアプリのひな型を作成します。
rails new spa --webpack=vue
--webpackはRailsでWeboackを使いやすくしたWebpackerというものを使用するというオプションです
Vue、React、Angular、Elm、Stimulusを使用することができます
今回はVue.jsを使用するので--webpack=vueとしています
次に、作成したRailsアプリのディレクトリへと移動します。
cd spa
Webpackerを使う場合、ruby ./bin/webpack-dev-serverというコマンドを実行しつつ、rails sでローカルサーバーを起動する必要があります
その為、現状のままではターミナルを複数開いておく必要があり、少々面倒です
そこで、複数のコマンドを並列して実行できるforemanを使用します
まず、Gemfileにgem 'foreman'を追記します
gem 'foreman'
その後、bundle install
bundle install
次に、foremanで使用するProcfile.devを作成します
web: bundle exec rails s
webpacker: ruby ./bin/webpack-dev-server
あとは、foreman start -f Procfile.devをターミナルで実行するだけです
foreman start -f Procfile.dev
localhost:5000にアクセスできればOkです(foremanを使用する場合、使用するポートが5000へと変更されています)
rails g controller コマンドを使い、静的なファイルを作成します
rails g controller web index
foreman start -f Procfile.devを実行して、localhost:5000/web/indexにアクセスできればOKです
app/javascript/packsディレクトリ内にindex.jsを作成します
app/javascript/packs/index.jsを以下のように変更します
import Vue from 'vue/dist/vue.esm';
const app = new Vue({
    el: '.app',
    data: function() {
        return {
            message: "Hello World! For Vue.js & Rails!"
        }
    }
})
次に、app/views/web/index.html.erbを以下のように変更します
<div class="app">
    
</div>
<%= javascript_pack_tag 'index' %>
foreman start -f Procfile.devを実行して、localhost:5000/web/indexにアクセスします
画面にHello World! For Vue.js & Rails!と表示されていればOKです
Webpackerを使用する場合は、JavaScriptパッケージマネージャのyarn経由でBootstrapをインストールします
yarn add bootstrap
付随して、jqueryとpopper.jsもインストールします
yarn add jquery
yarn add popper.js
次に、app/javascript/packs/index.jsとapp/assets/stylesheets/application.cssを以下のように変更します
import Vue from 'vue/dist/vue.esm';
import * as Bootstrap from 'bootstrap';
import 'bootstrap/dist/css/bootstrap';
Vue.use(Bootstrap);
const app = new Vue({
    el: '.app',
    data: function() {
        return {
            message: "Hello World! For Vue.js & Rails!"
        }
    }
})
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require bootstrap/dist/css/bootstrap
 *= require_tree .
 *= require_self
 */
これでBootstrapが使用できるようになります
では、実際にナビゲーションバーを作成してみます
app/javascript/packs/components/layouts/Header.vueを作成します
<template>
    <div>
        <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
            <a class="navbar-brand" href="#">SPA</a>
            <div class="dropdown">
                <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    Menu
                </button>
                <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                    <a href="/" class="dropdown-item">Top</a>
                    <a href="/about" class="dropdown-item">About</a>
                    <a href="/contact" class="dropdown-item">Contact</a>
                </div>
            </div>
        </nav>
    </div>    
</template>
app/views/web/index.html.erbとapp/javascript/packs/index.jsを以下のように変更します
<div class="app">
    <nav-bar></nav-bar>
    
</div>
<%= javascript_pack_tag 'index' %>
import Vue from 'vue/dist/vue.esm';
import * as Bootstrap from 'bootstrap';
import 'bootstrap/dist/css/bootstrap';
import Header from './components/layouts/Header.vue';
Vue.use(Bootstrap);
const app = new Vue({
    el: '.app',
    components: {
        'nav-bar': Header
    },
    data: function() {
        return {
            message: "Hello World! For Vue.js & Rails!"
        }
    }
})
foreman start -f Procfile.devでローカルサーバを起動して、localhost:5000/web/indexを開きます
ナビゲーションバーが表示されていると思います
まず、SPAとして表示する書くページをapp/javascript/packs/components/webディレクトリに作成します
<template>
    <div class="container">
        <h1>Index Pages</h1>
        <p>ここはIndexページです!</p>
    </div>    
</template>
<template>
    <div class="container">
        <h1>About Pages</h1>
        <p>ここはAboutページです!</p>
    </div>    
</template>
<template>
    <div class="container">
        <h1>Contact Pages</h1>
        <p>ここはContactページです!</p>
    </div>    
</template>
各ページのコンポーネントを作成後、yarn add vue-routerでvue-routerをインストールします
yarn add vue-router
次に、app/javascript/packs/router/router.jsを作成します
import Vue from 'vue/dist/vue.esm';
import VueRouter from 'vue-router';
import Index from '../components/web/Index.vue';
import About from '../components/web/About.vue';
import Contact from '../components/web/Contact.vue';
Vue.use(VueRouter);
export default new VueRouter({
    mode: 'history',
    routes: [
        { path: '/', component: Index },
        { path: '/about', component: About },
        { path: '/contact', component: Contact }
    ]
})
最後に、app/javascript/packs/index.js、app/views/web/index.html.erb、config/routes.rbを以下のように編集します
import Vue from 'vue/dist/vue.esm';
import * as Bootstrap from 'bootstrap';
import 'bootstrap/dist/css/bootstrap';
import Header from './components/layouts/Header.vue';
import Router from './router/router';
Vue.use(Bootstrap);
const app = new Vue({
    el: '.app',
    router: Router,
    components: {
        'nav-bar': Header
    },
    data: function() {
        return {
            message: "Hello World! For Vue.js & Rails!"
        }
    }
})
<div class="app">
    <nav-bar></nav-bar>
    <div class="container">
        <router-view></router-view>
    </div>
    
</div>
<%= javascript_pack_tag 'index' %>
Rails.application.routes.draw do
  root 'web#index'
  get '/about', to: 'web#index'
  get '/contact', to: 'web#index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
これで、SPAサンプルが作成できました!