【Nuxt.js】ログインフラグでレイアウトを切り替えるテクニック【2019/12/07追記あり】
  • 2019.11.24に公開
  • 2020.09.28に更新
  • SPA開発
  • 8. ログイン周りのレイアウト設計
  • No.1 / 4
「SPA開発」では、Nuxt.js v2.14未満が使用されています。 Nuxt.jsはv2.13~14で大きなバージョンアップがありました。それに伴い、書き方も大きく変化しています。 v2.14以上で書かれた「SPA開発」の続編は、カテゴリー「 Udemy 」 で公開しています。

2020年09月28日追記

Slackより有識者から「ログインなど機能はフロントに持たせないのがベターだと思います。フロントとバックの役割分担を明確にして、フロントはあくまでも"表現"UIに徹するべきだと考えます。」と言ったご意見をいただきました。

理由として下記2点です。

  1. ログイン後のページ情報(JSファイル)が_nuxtディレクトリ以下で誰でも確認できるため(下画像)、ログイン後のページ情報が解析されるリスクがある。
  2. ログインという本来の意図を無視できしまう可能性があること自体がアプリケーションの信頼性・品質を低くしてしまう恐れがある。

今回のアプリでは、ログイン後のページ情報を解析されても、そこにユーザー情報や機密情報がないため、大きな驚異に繋がる訳ではありません。

しかし、2の意見にあるように、そもそも「ログイン前とログイン後のフロントは切り分けるべきだ」という考えが認証アプリケーションの常識のようです。

この記事はNuxtの知識を深めることを目的としたサンプルアプリケーションの実装で、「実務で使えるNuxtの完璧なログイン機能」ではありません。

この記事を読み、「これでログイン機能ができるのか!」と勘違いされた皆さまにはこの場で謝罪します。申し訳ありません。

なお、具体的なログイン実装方法は

  • ウェルカムページ、ログインぺージ、パスワードリセットページなどのログイン前ページを表示するフロントと
  • ログイン後のページを表示するフロントを

切り分ける必要があります。

別アプリを用意してドメインを分ける方法、エントリポイントを分ける方法などがあるようです。

このあたりは筆者は未経験であり、今は詳しく説明することができません。また、知見を得た時にこの場所で紹介できればと考えています。

プログラミング技術はweb上に多数ありますが、考え方は実務でしか得られないものもあります。そう言った点でも有識者の方には、本当に貴重なご意見をいただきました。感謝いたします。

(追記終了)

_nuxtディレクトリ以下のログイン後のページ情報

2020-09-28 20-44-03

【2019/12/07追記】ログイン後のfooter.vueは使用しないとしました。

ログイン後のfooter.vueは、2つの理由で使用しない事としました。

  1. 重要性がないこと
  2. <v-navigation-drawer>と併用した時に下に固定表示され、ユーザーが見る画面領域が狭まる事

この変更に伴い、レイアウトファイルのdefault.vueを以下のように変更しました。

frontend/layouts/default.vue
<template>
  <v-app>
    <login-header />
    <nuxt />
    <!-- <my-footer /> 削除 -->
    <my-footer v-if="!$store.state.loggedIn" />	<!-- 追加 -->
  </v-app>
</template>

なお、記事は修正済みの内容となっています。

今回達成すること

今回はNuxt.jsのlayoutプロパティを使って、ログイン前と後でレイアウトを切り替えていきます。

完成イメージのgif

switching layout

レイアウトファイルの設計

レイアウトファイルは、ログインの前後でこのように切り替えます。

なお、default.vue以外のファイルは全て作成します。

ログイン前 ログイン後
レイアウトファイル home.vue default.vue
ヘッダーコンポーネント shared/header.vue shared/loginHeader.vue
フッターコンポーネント shared/footer.vue 同左 不要

ブランチを作成しときましょ

新しい作業に入るのでブランチを作成しておきましょう。

myapp $ git checkout -b login_layouting

作業に移る前に

今回の記事は全てNuxt.js上での作業となります。

ターミナルは、Rails内のNuxt.jsプロジェクト(筆者の場合、myapp/frontend)に移動しておいてください。

froutend $ # ここに移動しておく

それでは実装に移りましょう。

Eslintのルールを緩和する

まず、実装の前にEslintのルールを変更します。

確認のたびにエラーを吐き出されると困る2つのルールを緩和します。

  1. no-console

    console.logがある時にエラーを吐きます。

    warn(警告)に変更します。

  2. vue/no-unused-components

    template内で使われていないコンポーネントがある時にエラーを吐きます。

    warn(警告)に変更します。

frontend直下.eslintrc.js内のrulesプロパティにルールを追加します。

ちなみにルール付けは、error(エラー)、warn(警告)、off(何もしない) の3つを設定する事ができます。

frontend/.eslintrc.js
module.exports = {
  ...
  rules: {
    'no-console': 'warn', // 追記
    'vue/no-unused-components': 'warn'  // 追記
  }
}

componentsファイルの作成

componentsディレクトリにsharedディレクトリを作成し、その下3つのファイルを作成します。

  1. loginHeader.vue
  2. header.vue
  3. footer.vue
frontend $ mkdir components/shared && touch components/shared/{loginHeader.vue,header.vue,footer.vue}
  • touch {file1, file2, file3}

    touchコマンドで同じディレクトリ内に複数のファイルを一度に作成するテクニックです。

componentsディレクトリはこのようになります。

components
├── README.md
└── shared
    ├── footer.vue
    ├── header.vue
    └── loginHeader.vue

デフォルトで入っているlogo.vueは、必要ないので削除しました。

componentファイルの編集

作成した3つのファイルを以下のように編集しましょう。

frontend/components/shared/loginHeader.vue
<template>
  <div>
    ログイン後のloginHeader.vueを表示中
  </div>
</template>

<script>
export default {
}
</script>
frontend/components/shared/header.vue
<template>
  <div>
    ログイン前のheader.vueを表示中
  </div>
</template>

<script>
export default {
}
</script>
frontend/components/shared/footer.vue
<template>
  <div>
    footer.vueを表示中
  </div>
</template>

<script>
export default {
}
</script>

これでコンポーネントファイルが整いました。

layoutファイルの作成

ログイン前のトップページとして利用するhome.vueを作成します。

layoutsディレクトリ内に作成しましょう。

frontend $ touch layouts/home.vue

layoutsディレクトリはこのようになります。

frontend/layouts
├── README.md
├── default.vue
└── home.vue

ログイン前のレイアウト(home.vue)を編集

ログイン前のトップページとして利用するhome.vueから、ヘッダーとフッターコンポーネントを呼び出します。

ログイン前のヘッダーは「header.vue」を利用するので間違わないようにしてください。

frontend/layouts/home.vue
<template>
  <v-app>
    <my-header />
    このページはログイン前のレイアウト「home.vue」が使用されています。
    <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
  }
}
</script>

ログイン後のレイアウト(default.vue)を編集

ログイン後のレイアウトファイルdefault.vueからも同じくヘッダーとフッターを呼び出します。

ログイン後のヘッダーは「loginHeader.vue」を呼び出します。

frontend/layouts/default.vue
<template>
  <v-app>
    <login-header />
    <nuxt />
    <my-footer v-if="!$store.state.loggedIn" />
  </v-app>
</template>

<script>
import loginHeader from '~/components/shared/loginHeader.vue'
import myFooter from '~/components/shared/footer.vue'

export default {
  components: {
    loginHeader,
    myFooter
  }
}
</script>
  • <my-footer v-if="!$store.state.loggedIn" />

    ログインフラグがfalse、つまりログインしていない場合に表示します。

ログインフラグを扱うindex.jsファイルを作成する

ログインフラグをVuexに作成します。

storeディレクトリ内にindex.jsを作成しましょう。

frountend $ touch store/index.js

index.jsにloggedInを作成する

作成したindex.jsにログイン判定を行うフラグを作成します。

frontend/store/index.js
// 追記
export const state = () => ({
  loggedIn: false
})

レイアウトを切り替えるテクニック

それでは、index.vueにレイアウトを切り替える実装を行います。

と言っても簡単で、layoutプロパティに表示したいファイル名を文字列で渡します。

frontend/pages/index.vue
<script>
export default {
  // layoutプロパティを追記
  layout ({ store }) {
    return store.state.loggedIn ? 'default' : 'home'
  }
  ...
}
</script>

layout()には、layoutsディレクトリ内にあるファイル名を文字列で渡します。

また、単にレイアウトを変更する場合は以下のように書くことができます。

export default {
  layout: 'home'
}

ログインフラグを切り替えるリンクを作成する

ログインフラグを切り替えるリンクを作成していきましょう。

store/index.js

index.jsloggedInフラグを変更するactionメソッドを作成します。

frontend/store/index.js
export const state = () => ({
  loggedIn: false
})

// 以下、追記
export const mutations = {
  setLogin (state, payload) {
    state.loggedIn = payload
  }
}

export const actions = {
	userLogin ({ commit }, payload) {
		commit('setLogin', payload)
  }
}

ログイン、ログアウトページの作成

pagesディレクトリに、ログイン、ログアウトページを新たに作成します。

frontend $ touch pages/{login.vue,logout.vue}

pagesディレクトリはこのような構成になります。

pages
├── README.md
├── index.vue
├── login.vue
└── logout.vue

ログインページにリダイレクト設定を行う

/loginに遷移するとトップページにリダイレクトする設定を行います。

frontend/pages/login.vue
<template>
  <div />
</template>
<script>
export default {
  fetch ({ store }) {
    store.dispatch('userLogin', true)
  },
  created () {
    this.$router.replace('/')
  }
}
</script>
  • store.dispatch('userLogin', true)

    ログインページには、引数にtrueを渡しています。

  • this.$router.replace('/')

    ページ遷移と同時にトップページへ移動するよう設定しています。

ログアウトページにもリダイレクト設定を行う

こちらも同じく、/logoutに遷移するとトップページにリダイレクトする設定を行います。

frontend/pages/logout.vue
<template>
  <div />
</template>
<script>
export default {
  fetch ({ store }) {
    store.dispatch('userLogin', false)
  },
  created () {
    this.$router.replace('/')
  }
}
</script>
  • store.dispatch('userLogin', false)

    ログアウトページには、引数にfalseを渡しています。

トップページにリンクをセットする

home.vueには、/loginリンクをセットします。

frontend/layouts/home.vue
<template>
  <v-app>
    <my-header />
    このページはログイン前のレイアウト「home.vue」が使用されています。
    <!-- 追記 -->
    <nuxt-link to="/login">
      ログインする
    </nuxt-link>
    <!-- 追記終了 -->
    <my-footer />
  </v-app>
</template>
...

index.vueには、/logoutリンクをセットします。

frontend/pages/index.vue
<template>
  <v-container fluid fill-height>
    <v-row
      justify="center"
      class="text-center"
    >
      <!-- 追記 -->
      <v-col cols="12">
        <nuxt-link to="/logout">
          ログアウト
        </nuxt-link>
      </v-col>
      <!-- 追記終了 -->
      ...
</template>

最後に確認してみましょう

以上で実装は完了です。

Nuxt.jsを起動した後に"http://localhost:3333/"にアクセスして確認してみましょう。

frontend $ yarn dev

switching layout

コミットしとこ

さて、ここまでの変更をコミットしておきましょう。

一度Railsプロジェクトに戻ります。

frontend $ cd ../

commitしましょう。

myapp $ git add -A
myapp $ git commit -m "add_layout_files"

まだ、masterブランチにはマージしません。

まとめ

今回は、ログイン前とログイン後に利用する、レイアウトファイルとコンポーネントファイルを作成しました。

ログイン前 ログイン後
レイアウトファイル home.vue default.vue
ヘッダーコンポーネント shared/header.vue shared/loginHeader.vue
フッターコンポーネント shared/footer.vue 同左 不要

Nuxt.jsのレイアウトは、デフォルトでdefault.vueが読み込まれます。

このdefault.vueを主に利用するレイアウト設計をした方が、切り替え作業が最小に抑えられます。

頭の隅っこに覚えておいてください。

さて、次回は?

今のままだとかなりブサイクなので、次回はヘッダーとフッターを作り込んでいきます。

どうぞお楽しみに。

あなたの力になれること
私自身が独学でプログラミングを勉強してきたので、一人で学び続ける苦しみは痛いほど分かります。そこで、当時の私がこんなのあったら良いのにな、と思っていたサービスを立ち上げました。周りに質問できる人がいない、答えの調べ方が分からない、ここを聞きたいだけなのにスクールは高額すぎる。そんな方に向けた単発・短期間メンターサービスを行っています。
独学プログラマのサービス
SPA開発の投稿
1
  • 更新情報
  • /
  • #01
「Rails apiとNuxt.jsでSPA開発」のデモアプリを開発中...。【2020/05/19追記: このカテゴリーの更新を一旦終了といたします】
1
  • 今回作るアプリケーション
  • /
  • #01
Railsアプリの完成イメージ画像と作ろうと思った経緯
2
  • 今回作るアプリケーション
  • /
  • #02
今回作るRailsアプリの全体像と機能の整理
1
  • 開発環境を整える
  • /
  • #01
macにRailsをゼロからインストールする
2
  • 開発環境を整える
  • /
  • #02
Rails apiモードのプロジェクトを作成し、Gitにコミットする
3
  • 開発環境を整える
  • /
  • #03
Bitbucketに公開鍵を追加し、Railsプロジェクトをpushする
4
  • 開発環境を整える
  • /
  • #04
HerokuCLIのインストールとherokuアプリケーションの作成
1
  • RailsをHerokuにデプロイする
  • /
  • #01
Herokuのデータベース設定と開発に便利なgemを導入する
2
  • RailsをHerokuにデプロイする
  • /
  • #02
HerokuにPumaを導入するためのRailsセットアップ
3
  • RailsをHerokuにデプロイする
  • /
  • #03
Railsに"Hello"を表示してHerokuへデプロイする
1
  • RailsとNuxt.jsを共存させる
  • /
  • #01
【RailsとNuxt.jsの共存】Rails上にNuxt.jsのプロジェクトを構築しよう
2
  • RailsとNuxt.jsを共存させる
  • /
  • #02
Nuxt.jsからRailsへ、初めてのapi通信でHelloを表示しよう
3
  • RailsとNuxt.jsを共存させる
  • /
  • #03
Nuxt.jsにVuetify2.0を導入してFont Awesomeもインストールするぜ
4
  • RailsとNuxt.jsを共存させる
  • /
  • #04
初めてのRailsApiアプリの公開。Herokuにデプロイする準備と実際のデプロイまで
1
  • データベース設計
  • /
  • #01
データベースを正規化する前に、会計システムの勘定科目データを整理する
2
  • データベース設計
  • /
  • #02
会計システムのデータベース設計に挑む
1
  • バージョンアップ情報
  • /
  • #01
【ご報告】Nuxt.jsを2.10.2にバージョンアップしました
2
  • バージョンアップ情報
  • /
  • #02
【ご報告】Railsを6.0.0にバージョンアップしました
1
  • Userモデル開発
  • /
  • #01
本番環境と開発環境でRailsのSeedデータを切り替える
2
  • Userモデル開発
  • /
  • #02
Railsにユーザーテーブルを作成する【テーブル確認コマンド】
3
  • Userモデル開発
  • /
  • #03
【Rails】EachValidatorクラスを使ったEmailカスタムバリデーション【lib以下読み込み】
4
  • Userモデル開発
  • /
  • #04
【Rails】エラーメッセージの日本語化【i18nとja.ymlのセッティング】
5
  • Userモデル開発
  • /
  • #05
【Rails】開発・テスト・本番環境の全てにユーザーSeedデータ投入する
6
  • Userモデル開発
  • /
  • #06
【Rails】ユーザーモデルのバリデーションをテストする
1
  • ログイン周りのレイアウト設計
  • /
  • #01
【Nuxt.js】ログインフラグでレイアウトを切り替えるテクニック【2019/12/07追記あり】
2
  • ログイン周りのレイアウト設計
  • /
  • #02
【Nuxt.js】ウェルカムページのレイアウト構築【sassの導入】
3
  • ログイン周りのレイアウト設計
  • /
  • #03
【Nuxt.js】ログイン周りの入力フォームコンポーネント設計【2019/12/07追記あり】
4
  • ログイン周りのレイアウト設計
  • /
  • #04
【Nuxt.js】会員登録フォームを構築してサインアップページを完成させる
独学プログラマ
独学でも、ここまでできるってよ。
CONTACT
Nuxt.js制作のご依頼は下記メールアドレスまでお送りください。