今回達成すること
今回は、ログイン前のトップページに表示されるウェルカムページを作成していきます。
以下の手順で進めていきます。
- アプリ全体で利用する、共通タイトルの設定
- ログイン前のヘッダー(header.vue)の編集
- Nuxt.jsにsassを導入
- 新規会員登録ページ(signup.vue)を作成
- ログイン前後、共通で利用するフッター(footer.vue)の編集
- ログイン前のレイアウトファイル(home.vue)の編集
なお、最終的にトップページはこのようになります。
完成イメージ
筆者の
作業に移る前に
今回の記事は全てNuxt.js上での作業となります。
ターミナルは、Rails内のNuxt.jsプロジェクト(筆者の場合、myapp/frontend)に移動しておいてください。
froutend $ # ここに移動しておく
共通タイトルの設定
まず、アプリで使用する共通タイトルを設定していきます。
ヘッダーに表示したり、フッターのコピーライトに表示するアプリ名のことですね。
今のタイトルはどこから表示されているか?
現状、筆者の場合では「frontend」という名前がページタイトルとして表示されています。
これはNuxt.jsの作成時に決めたプロジェクト名が反映されています。
どこで設定されているかというと、name
というプロパティです。
frontend/package.json
{
"name": "frontend",
...
}
ここのname
を、head
プロパティでタイトルとして設定しています。
frontend/nuxt.config.js
const config = {
mode: 'spa',
head: {
title: process.env.npm_package_name || '',
...
つまり、
共通タイトルを書き換えて表示する
仕組みがわかったところで、
frontend/package.json
{
"name": "demoApp", // 自由な名前でOK
...
}
クライアント側で使えるようにenvプロパティを登録
今のままコンポーネント内でprocess.env.npm_package_name
を利用しようとしても、空の値が返されます。
何故かというと、process.env
の中身はサーバー側の値であり、クライアント(ブラウザ)側からは読み込めないためです。
そこで、サーバー側の値をクライアント側でも利用できるよう、env
プロパティを登録します。
frontend/nuxt.config.js
const config = {
...
// 追記
env: {
APP_NAME: process.env.npm_package_name
}
}
この設定により、クライアント側でprocess.env.APP_NAME
という環境変数が利用できるようになりました。
共通タイトルを確認しましょう
ログイン前のヘッダーコンポーネント、
frontend/components/shared/header.vue
<template>
<div>
{{ appName }}
</div>
</template>
<script>
export default {
data: () => ({
appName: process.env.APP_NAME
})
}
</script>
package.jsonで指定したアプリ名が表示されます。
ログイン前のヘッダー「header.vue」を編集する
さて、次はこんな感じ↓にログイン前のヘッダーを編集していきます。
完成イメージ
componentsディレクトリ内の
frontend/components/shared/header.vue
<template>
<div>
<v-app-bar
elevation="1"
>
<v-toolbar-title>
<nuxt-link
to="/"
>
{{ appName }}
</nuxt-link>
</v-toolbar-title>
<v-spacer />
<v-toolbar-items
v-for="(link, i) in links"
:key="i"
>
<v-btn
:to="link.to"
text
class="font-weight-bold"
>
{{ link.title }}
</v-btn>
</v-toolbar-items>
</v-app-bar>
</div>
</template>
<script>
export default {
data: () => ({
appName: process.env.APP_NAME,
links: [
{ title: '新規会員', to: '/signup' },
{ title: 'ログイン', to: '/login' }
]
})
}
</script>
-
v-app-bar
Vuetifyの
v-toolbar
でも同じヘッダーを作成できますが、今回はv-app-bar
を採用しました。v-app-bar
は、様々なスクロールイベントを付与することができます。 -
elevation="1"
これはツールバーの影の濃さを数字で指定します。0〜24の値を指定できます。
ただ...ちょっとアプリ名がリンク色に染まってブサイクですね...。
Nuxt.jsにsassを導入する
sassを導入してオリジナルのCSSクラスを作成しましょう。
今回は公式のインストール方法に従ってsassを導入します。
1. node-sass と sass-loaderをインストールする
ターミナルより、sass実行に必要なモジュールをインストールします。
frontend $ yarn add node-sass sass-loader
2. main.scssファイルの作成
assets直下にcssディレクトリと、
frontend % mkdir assets/css && touch assets/css/main.scss
assetsディレクトリの構成は以下のようになります。
assets
├── README.md
└── css
└── main.scss
3. nuxt.config.jsにCSSファイルを登録
続いて
frontend/nuxt.config.js
const config = {
...
css: [
'@/assets/css/main.scss' // 追記
],
}
以上で設定は完了です。
これでsassが利用できるようになりました。
main.scssにオリジナルクラスを作成する
frontend/assets/css/main.scss
$black: rgba(0, 0, 0, 0.87);
// commons //////////////////////////
body {
word-wrap: break-word;
overflow-wrap: break-word;
}
a.link-black {
color: $black !important;
text-decoration: none;
}
-
$black: rgba(0, 0, 0, 0.87);
$black
には、Vuetifyのブラックと一致する色を指定しています。
header.vueにクラスを付け加える
作成したlink-black
クラスをアプリ名に付け加えましょう。
frontend/components/shared/header.vue
<template>
...
<nuxt-link
to="/"
class="link-black font-weight-bold" <!-- 追記 -->
>
{{ appName }}
</nuxt-link>
よし、これでアプリ名がブサイクではなくなりました!
新規会員登録ページ「signup.vue」を作成する
今のままヘッダーの「新規会員」をクリックすると、ページが無いためエラーになります。
そこで
frontend $ touch pages/signup.vue
作成した
frontend/pages/signup.vue
<template>
<div>
新規会員登録ページ
</div>
</template>
<script>
export default {
}
</script>
これにて「header.vue」は完成です
以上でログイン前のheader.vueは完成です。
共通のフッター「footer.vue」を編集する
続いて
完成イメージ
frontend/components/shared/footer.vue
<template>
<v-footer
padless
>
<v-col
class="text-center"
cols="12"
>
<div class="body-2">
&copy;{{ copyRightYear }} — <strong>{{ appName }}</strong>
</div>
</v-col>
</v-footer>
</template>
<script>
export default {
data: () => ({
appName: process.env.APP_NAME
}),
computed: {
copyRightYear () {
const start = 2019
const now = new Date().getFullYear()
return (start === now) ? start : `${start} - ${now}`
}
}
}
</script>
-
padless
これはfooterの
padding
を削除するVuetifyのプロパティです。 -
copyRightYear ()
現在の年度とアプリ制作年度を比較して、コピーライトの表記を自動化しています。
2019年の場合 => 「©2019 — demoApp」
2020年の場合 => 「©2019 - 2020 — demoApp」
OK!完成イメージ通りのフッターが作成できましたね。
最後。レイアウトファイル「home.vue」を編集する
layputsディレクトリ内に作成した
よくwebアプリのトップページにある「ようこそ」や「アプリの説明」を表示するページのことです。
<v-content>
タグ内に、自由にコンテンツを作成してください。
frontend/layouts/home.vue
<template>
<v-app>
<my-header />
<v-content>
<!-- ここに自由に追記 -->
</v-content>
<my-footer />
</v-app>
</template>
<script>
import myHeader from '~/components/shared/header.vue'
import myFooter from '~/components/shared/footer.vue'
export default {
components: {
myHeader,
myFooter
},
data: () => ({
appName: process.env.APP_NAME
})
}
</script>
-
<v-content>
大切なのは、この
<v-content>
タグの中にメインコンテンツを書くということです。もしこのタグで囲まない場合、コンテンツの高さが足りない時にフッターが上がってきます。
これはVuetifyのレイアウトの仕組みによるものです。
v-contentタグで囲まない場合の悪い例
本番環境にpushしておきましょう
さて、home.vueの編集が完了したら、Railsプロジェクトに戻ってHerokuにPushしましょう。
frontend $ cd ../
myapp $ git add -A
myapp $ git commit -m "welcome_page_layouts"
myapp $ git checkout master
myapp $ git merge login_layouting
myapp $ git push
myapp $ git push heroku
pushが完了したら元のレイアウトブランチに戻っておきます。
myapp $ git checkout login_layouting
myapp $ git branch
* login_layouting
master
まとめ
さて、今回の学んだポイントをおさらいします。
- アプリの共通タイトルは
package.json のname
プロパティで管理する。 - サーバーサイドとフロントエンドで環境変数を共有したい場合は、
nuxt.config.js のenv
に登録する。 - Nuxt.jsにsassを導入する時は、
node-sass
とsass-loader
モジュールをインストールする。 - メインコンテンツは、
<v-content>
タグで囲む。(Vuetifyの場合)
以上となります。
お疲れでした!(長い戦いだった。。。)
さて、次回は?
さてさて、次回「新規会員登録ページ」のレイアウト構築と、メールアドレス、パスワードの入力フォームの導入を行います。
どうぞ、お楽しみに!
筆者のhome.vue
筆者のサンプルコードです。
frontend/layouts/home.vue
<template>
<v-app>
<my-header />
<v-content>
<v-parallax
dark
src="https://cdn.vuetifyjs.com/images/backgrounds/vbanner.jpg"
>
<v-row
align="center"
justify="center"
>
<v-col
class="text-center"
cols="12"
sm="8"
>
<h1 class="display-1 mb-4">
ようこそ!{{ appName }}へ
</h1>
<v-list-item
href="https://blog.cloud-acct.com/categories/spa"
target="_blank"
rel="noopener noreferrer"
>
<v-list-item-content>
<h2 class="subtitle-1 font-weight-medium white--text">
このアプリの作り方を見る
</h2>
</v-list-item-content>
</v-list-item>
</v-col>
</v-row>
</v-parallax>
<v-container>
<v-row
justify="center"
>
<v-col
class="text-center"
cols="12"
>
<div>
{{ appName }}では以下の技術を採用しています。
</div>
</v-col>
<v-col
v-for="(item, i) in cardItems"
:key="i"
class="text-center"
cols="12"
:sm="12 / cardItems.length"
>
<v-avatar
:color="item.color"
:size="(600 / cardItems.length) - 30"
>
<span class="white--text display-1">
{{ item.name }}
</span>
</v-avatar>
<v-card
flat
color="transparent"
>
<v-card-title class="justify-center">
{{ item.name }} {{ item.version }}
</v-card-title>
<v-card-text>
{{ item.description }}
</v-card-text>
</v-card>
</v-col>
<v-col
class="text-center"
cols="12"
>
<div>
このアプリの作り方は、チュートリアル形式で公開されています。
</div>
<a
href="https://blog.cloud-acct.com/categories/spa"
target="_blank"
rel="noopener noreferrer"
>
このアプリの作り方を見る
</a>
</v-col>
</v-row>
</v-container>
</v-content>
<my-footer />
</v-app>
</template>
<script>
import myHeader from '~/components/shared/header.vue'
import myFooter from '~/components/shared/footer.vue'
export default {
components: {
myHeader,
myFooter
},
data: () => ({
appName: process.env.APP_NAME,
cardItems: [
{
name: 'Rails',
color: '#CC3C33',
version: '6.0.0',
description: 'サーバーサイドにRails APIモードを採用'
},
{
name: 'Nuxt.js',
color: '#00C550',
version: '2.10.2',
description: 'フロントエンドにNuxt.js SPAモードを採用'
},
{
name: 'Vuetify',
color: '#2271C6',
version: '2.1.9',
description: 'UIフレームワーク'
}
]
})
}
</script>