LoginSignup
8
12

More than 5 years have passed since last update.

MyFirstRails #5 RailsとVue.jsでSPAを作ってみよう!

Posted at

SPA サンプル

概要

Railsにこれから初めて触れる方を対象にしたチュートリアルです
RailsとVue.jsを使ってSPA(シングルページアプリケーション)のサンプルを作成します

実際に作ったものはこちら

チュートリアル

Railsのひな型を作る

まず、rails newを実行し、Railsアプリのひな型を作成します。

rails new spa --webpack=vue

--webpackはRailsでWeboackを使いやすくしたWebpackerというものを使用するというオプションです

Vue、React、Angular、Elm、Stimulusを使用することができます

今回はVue.jsを使用するので--webpack=vueとしています

次に、作成したRailsアプリのディレクトリへと移動します。

cd spa

Foremanを使う

Webpackerを使う場合、ruby ./bin/webpack-dev-serverというコマンドを実行しつつ、rails sでローカルサーバーを起動する必要があります

その為、現状のままではターミナルを複数開いておく必要があり、少々面倒です

そこで、複数のコマンドを並列して実行できるforemanを使用します

まず、Gemfilegem 'foreman'を追記します

Gemfile
gem 'foreman'

その後、bundle install

bundle install

次に、foremanで使用するProcfile.devを作成します

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です

Vue.jsを使う

app/javascript/packsディレクトリ内にindex.jsを作成します

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を以下のように変更します

app/views/web/index.html.erb
<div class="app">
    {{message}}
</div>

<%= javascript_pack_tag 'index' %>

foreman start -f Procfile.devを実行して、localhost:5000/web/indexにアクセスします
画面にHello World! For Vue.js & Rails!と表示されていればOKです

Bootstrapの導入

Webpackerを使用する場合は、JavaScriptパッケージマネージャのyarn経由でBootstrapをインストールします

yarn add bootstrap

付随して、jquerypopper.jsもインストールします

yarn add jquery
yarn add popper.js

次に、app/javascript/packs/index.jsapp/assets/stylesheets/application.cssを以下のように変更します

app/javascript/packs/index.js
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!"
        }
    }
})
app/assets/stylesheets/application.css
/*
 * 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を作成します

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.erbapp/javascript/packs/index.jsを以下のように変更します

app/views/web/index.html.erb
<div class="app">
    <nav-bar></nav-bar>
    {{message}}
</div>

<%= javascript_pack_tag 'index' %>
app/javascript/packs/index.js
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を開きます
ナビゲーションバーが表示されていると思います

vue-routerによるSPA作成

まず、SPAとして表示する書くページをapp/javascript/packs/components/webディレクトリに作成します

app/javascript/packs/components/web/Index.vue
<template>
    <div class="container">
        <h1>Index Pages</h1>

        <p>ここはIndexページです!</p>
    </div>    
</template>
app/javascript/packs/components/web/About.vue
<template>
    <div class="container">
        <h1>About Pages</h1>

        <p>ここはAboutページです!</p>
    </div>    
</template>
app/javascript/packs/components/web/Contact.vue
<template>
    <div class="container">
        <h1>Contact Pages</h1>

        <p>ここはContactページです!</p>
    </div>    
</template>

各ページのコンポーネントを作成後、yarn add vue-routervue-routerをインストールします

yarn add vue-router

次に、app/javascript/packs/router/router.jsを作成します

app/javascript/pack/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.jsapp/views/web/index.html.erbconfig/routes.rbを以下のように編集します

app/javascript/packs/index.js
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!"
        }
    }
})
app/views/web/index.html.erb
<div class="app">
    <nav-bar></nav-bar>
    <div class="container">
        <router-view></router-view>
    </div>
    {{message}}
</div>

<%= javascript_pack_tag 'index' %>
config/routes.rb
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サンプルが作成できました!

8
12
0

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
8
12