前回の記事ではRails6環境でRailsの「webpacker」を使用せず、
フロントエンドをwebpackにそれぞれ役割分担させよう!という趣旨の記事を書きました。
少し続きまして、今回は具体的にVue.jsを使ってフロント周りをどんな感じに作っていくのかを、ディレクトリ構成と役割をメインに一つの例を紹介したいと思います。
今回もこちらの記事をベースにしています(ありがたや)↓
Rails環境でJS , CSSをwebpackで完全に管理する
前回の記事はこちら↓
目次
フロントエンドは「frontend」ディレクトリの中で管理する
Railsプロジェクトのルート直下に「frontend」ディレクトリを置き、この中に以下のようなディレクトリ構成を作ります。
分かりづらいですが、●がついているのはディレクトリです。
Vue.jsでフロント周りをどこまで制御させるか(Vuexを使って完全なSPAサイトを作る等)にもよりますが、
Railsのページリダイレクトはコントローラ単位で行い、同じコントローラ内のデータ通信はリダイレクトせずに非同期通信を行って画面制御をVue.jsに任せる、「部分的SPA」なサイトを今回構築しようと思います。
Railsとwebpackでバックとフロントに役割分担させる!と上で言いましたが、厳密には「Railsでもフロントを触るけどwebpackがメインだよ」と思ってください。
また、既存のプロジェクトをVue化させる場合、この方法が分かりやすくていいんじゃないかなと個人的に思っています。
ちなみに、私のプロジェクトでの使用例↓
「frontend」ディレクトリの役割について
compornents
ここではheader.vueやfutter.vueなど各画面で共通的に使うvueコンポーネントを格納しておきます。
Railsでいうところの「layout」ディレクトリに管理するテンプレートファイルに似ています。
image
画像ファイルを保管しておきます。
ちなみに、RailsのPublicディレクトでも今まで通り画像を保管しておくことができます。
pages
コントローラごと(ページごと)にディレクトリを切って、各画面を構成するvueコンポーネントを管理します。
例えば、「hogepage_controller.rb」なら「hogepage」というディレクトリを作成してその中に「index.vue」「hogepageIndex.js」を作成して管理します。
index.vue、hogepageIndex.jsというファイルが出てきましたが、それぞれどんなの役割があるのか説明します。
・index.vue
「hogepage」ページを構成するコンポーネントファイルです。
componentディレクトリ内に作成したコンポーネントをimportで呼び出して、「components: {}」内に指定しておけば<template>内で使用することが出来ます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<template> <div id="hogepage-index"> <mainpage></mainpage> <div> <!-- 処理を記述 --> </div> <mainfooter></mainfooter> </template> <script> // components内のコンポーネントファイルを呼び出す import header from "../../components/header"; import futter from "../../components/futter"; export default { components: { header, footer }, data() { return { hogehoge: "" } }; </script> <style lang="scss" scoped> </style> |
・hogepageIndex.js
Railsのhogepage.html.erbファイル(Viewファイル)からindex.vueコンポーネントを使えるようにするためのファイルです。
1 2 3 4 5 6 7 8 9 |
import Vue from 'vue' import HogepageIndex from './index' new Vue({ el: '#app', components: { HogepageIndex // これでViewファイル内では<hogepage-index></hogepage-index>で呼べます。 } }) |
前回の記事を参照してもらいたいのですが、実は作成した「webpack.config.js」の設定で、画面読み込みが開始された時に、その画面に対応する「/pages/~/~.js」ファイルを「entry」に設定して始めに読み込むようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
const path = require('path') const glob = require('glob') const webpack = require('webpack') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const VueLoaderPlugin = require('vue-loader/lib/plugin') const ManifestPlugin = require('webpack-manifest-plugin') let entries = {} glob.sync('./frontend/pages/**/*.js').map(function (file) { let name = file.split('/')[4].split('.')[0] entries[name] = file }) return { entry: entries, ///// 以下省略 ///// } |
これらの画面構成ファイルにともなって、Rails側の「hogepage/index.html.erb」ファイルと「layout/application.html.erb」を以下のように修正し、コンポーネントを呼び出します。
・layout/application.html.erb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- ビューポートの設定 --> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Hogeページ</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= javascript_bundle_tag "#{params[:controller]}#{params[:action].capitalize}" %> <%= stylesheet_bundle_tag "#{params[:controller]}#{params[:action].capitalize}" %> </head> <body> <%= yield %> </body> </html> |
「javascript_bundle_tag」「stylesheet_bundle_tag」は前回の記事で作成した自前のJS/CSS読み込みヘルパーメソッドです。
参考記事の方では「<%= yield%>」を「<div id=”app”>」で囲っていますが、各ページのhtml.erbファイルで臨機応変に記述出来るようにここでは書かずに各html.erbで記述するように変更します。
・hogepage/index.html.erb
1 2 3 4 5 6 7 8 |
<div id="app"> <hogepagek-index></hogepage-index> </div> <script> // ここにグローバル変数や処理を書くこともできます。 // <%=@hoge%>のようなインスタンス変数も扱えます。 </script> |
参考記事の方では「<hogepage-index>」のみが記述されていますが、上記した通り、臨機応変に使いたいのでこのように<div id=”app”>タグで囲っています。
plugins
画面で汎用的に使う共通JavaScript/cssファイルを管理します。
JavaScriptファイルは、vueコンポーネントで呼び出して使用するため、関数に「export」を付ける事をお忘れなく。
cssはscss形式で管理し、vueのstyleタグ内で呼び出します。
1 2 3 |
export function hogehoge() { // 処理 } |
1 2 3 4 |
/* 共通スタイル */ body { background-color: #f7f7f7; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<template> <div id="hogepage-index"> <mainpage></mainpage> <div> <!-- 処理を記述 --> </div> <mainfooter></mainfooter> </template> <script> // components内のコンポーネントファイルを呼び出す import header from "../../components/header"; import futter from "../../components/futter"; import * as hoge from "../plugins/hoge.js"; export default { components: { header, footer }, data() { return { hogehoge: "" }, methods: { hugahuga: function { // hoge.jsの関数hogehogeを呼び出す hoge.hogehoge(); } } }; </script> <style lang="scss" scoped> /* importしてhoge.scssを呼び出す */ @import "../plugins/hoge.scss"; </style> |
public
このディレクトリの中身はwebpackによって出力されたバンドルファイルが格納されます。
webpack.config.jsで「/public/assets」以下にバンドルファイルと「manifest.json」を出力させるように設定しているので、こちらが作成するのは「/public/assets」までです。(確か…)
manifest.jsonファイルではバンドルされたJavaScriptとcssファイルを確認することが出来ます。
まとめ
今回紹介したのは、Rails×Vue.js開発の最適解ではなく、1つの例です。
フロント周りをVueに比重を置くか、Railsに比重を置くかで複雑に状況が変わってくると思います。
自身のプロジェクトにマッチするVueの使い方を見つけ出す手助けになれば幸いです。