Nuxt(SPA)+Firebaseでログイン処理を実装する



# はじめに

今回は、NuxtとFirebaseを使って認証処理を実装した時の記録を記事として残しておきます。
※NuxtはTypescriptで実装するようにしています。

## 作業環境

```
OS: Windows 10 Pro
Node: 12.1.0
npm: 6.9.0 
Yarn: 1.15.2
```

## Nuxtを選択する

NuxtはVueの公式ガイドラインに沿って強力なアーキテクチャを提供するように設計されたフレームワークとのことです。
コーディングの統一性が高い分、大規模なプロジェクトでも手軽に組めてしまいます。
Vue単体で一からプロジェクトを構築するのも良いのですが、最初からある程度規約が整っているNuxtで開発を進めると複数の開発者がいる場合なんかは作業効率が跳ね上がりますね。
逆に、既存のプロジェクトに対して一部Vueのアプリを取り入れるみたいな時はNuxtを使わずにVue単体で構築するのが吉でしょう。

### VueCLI3でもよくない？
Vueのプロジェクトを構築するにあたり、**VueCLI3**もしくは**Nuxt**のどちらかで作り始めるという話がよくあります。

私の場合、個人でも開発できてしまうような小規模なものにはVueCLI3を採用したりしています。
VueCLI3を使用すれば、プロジェクト作成時にVueRouter、Vuex、TypeScript等を選択すれば十分に満足のできるテンプレートが出来上がりますからね。

ページ数の多さ、データの状態管理の多さ、複数の開発者といったような場合はNuxtを採用したりします。
Nuxtは規約重視なフレームワークになっておりますので、実装の統一性という面から採用します。
また、SSRを取り入れたい時はNuxtの出番ですね。
Vue単体でSSRやる場合はけっこう設定が面倒だったりします。（[VueでSSR](https://ssr.vuejs.org/)）
さらに、Nuxtはサーバーミドルウェアを構築できたりします。
外部サーバを用意せずにJavascriptでAPIを用意したい時なんかはNuxtだけで実現できてしまいます。





## Firebaseを選択する

Firebaseとは、言わずと知れたGoogleが提供しているWebアプリケーションのバックエンドサービスですね。
[ドキュメント](https://firebase.google.com/docs?hl=ja)も分かりやすく、流行りのサーバレスアーキテクチャを学習コストほぼなしで実現できちゃいます。
サーバレスアーキテクチャってのはバックエンド系は任せちゃうやつです。
例えば、Web開発を行っていくうえで、NodeJSやPHP,Pythonを使ってDB操作や認証処理とかをバックエンド側として実装したりしますね。（DBを自前で用意してModel作って、、、リクエストされたpayloadからトークン発行して、、、などのアレです。）
アレをやらなくて済みます。



# 準備

## Firebaseを始めてみる

まずはGoogleのアカウントを用意しましょう。
用意ができたら、[Firebase Console](https://console.firebase.google.com/)へアクセスします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/000cbb7c-2544-6149-353a-60712f3c2c8f.png)
上記の画面を確認したら、プロジェクトを作成を押します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/a18da710-ceff-0f2c-ea57-05f4f86f7f75.png)
上記の画面では、適当なプロジェクト名を入力して規約同意にチェックして続行を押します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/603379e7-169a-5997-3bd1-607d1124e723.png)
上記の画面は、Googleアナリティクスを有効にするかどうかです。チェックして続行を押します。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/8d68d903-1d6a-9588-54c9-6f4b2fff8d44.png)
先ほどの画面で、Googleアナリティクスを有効にチェックをしました。
そのため、アナリティクス対象の地域を選択したり、分析データの共有同意を求められます。
チェックしてプロジェクトを作成ボタンを押します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/2eed520c-843a-dccb-2fce-fbded0d328c2.png)
少し時間が経つとプロジェクトが作成されます。続行を押します。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/59291f64-fb79-8f09-80a2-3f2b3ccaa2ac.png)
無事にプロジェクトの作成が終わりました。
[Firebase Console](https://console.firebase.google.com/)からいつでも入れます。

**※Googleアナリティクス**
プロジェクト作成中にあったGoogleアナリティクスについてですが、
有効にしておくとアプリの使用状況とユーザーエンゲージメントについて分析できたりします。
ユーザの行動を把握してアプリのマーケティング方法の決定を決めるのに利用したり出来るようですね。
私はマーケティング経験も知識もないので使い道は良く知りませんが。。

## Nuxtを始めてみる

```
$ npx create-nuxt-app <project-name>
# もしくは
$ yarn create nuxt-app <project-name>
```
[公式](https://ja.nuxtjs.org/guide/installation/)を見ると上のコマンドで始められるとあります。
ローカルの環境に**npxコマンド**もしくは**yarn コマンド**が必要みたいですね。
`npx`や`npm`や`yarn`は Node.js のパッケージを管理するためのManagerツールですね。
例えば聞き慣れたNode系パッケージの`express`なんかをプロジェクト内に手軽にインストールできたりします。

### npmとnpxは何が違うのか
`npm`も`npx`もNodeパッケージをインストールする時に使用します。
ですが、インストールしたパッケージの実行方法が異なります。

`npm`で**グローバル**にパッケージをインストールした時はパスの設定が自動的に行われるのでコマンドの実行が行えますが、**ローカル**にインストールした場合はコマンドでの実行がやや面倒くさくなります。
**ローカル**の場合は、`./node_modules/.bin/xxx`もしくは`$(npm bin)/xxx`とコマンドが配置されている場所を指定してあげる必要があるんです。

ですが、`npx`の場合は**グローバル**だろうと**ローカル**だろうと関係なくコマンド実行できてしまうんです。
`npx xxx`で実行できます。
また`./node_modules/.bin/xxx`のようにパッケージを実行するためには当然、`node_modules`の中にパッケージがインストールされている必要がありますよね。
`npx`コマンド場合はパッケージがインストールされていなくても実行できてしまいます。
実行する前に、一時的に該当パッケージがインストールされるようですね。

一例を実行してみたので下記ご参照ください。

```
PS C:\Users\user\Desktop> npm inatall envinfo
# envinfoがあるので実行できます。
PS C:\Users\user\Desktop> ./node_modules/.bin/envinfo
  System:
    OS: Windows 10
    CPU: (4) x64 Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz

PS C:\Users\user\Desktop> npm uninatall envinfo
# envinfoがないので怒られます。
PS C:\Users\user\Desktop> ./node_modules/.bin/envinfo
./node_modules/.bin/envinfo : 用語 './node_modules/.bin/envinfo' は、コマンドレット、関数、スクリプト ファイル、
または操作可能なプログラムの名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている
場合はそのパスが正しいことを確認してから、再試行してください。

# envinfoがないのに実行できます。（一時的にインストールして実行）
PS C:\Users\user\Desktop> npx envinfo
npx: 1個のパッケージを3.183秒でインストールしました。
  System:
    OS: Windows 10
    CPU: (4) x64 Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz
```

### yarnとnpmは何が違うのか？
まずは、パッケージインストール等のコマンドの指定方法が異なります。

```
$ npm install express # npmでexpressをインストール!!
$ yarn add express # yarnでexpressをインストール!!
$ npm uninstall express # npmでexpressをアンインストール!!
$ yarn remove express # yarnでexpressをアンインストール!!
```
また、`yarn`は並列でパッケージをインストールができるため`npm`よりパッケージのインストールが高速らしいです。
さらに、`npm`でインストールしたパッケージも`yarn`で実行できます。
そして、パッケージの実行を`npx`みたいに`yarn xxx`で実行できます。
※ただし、`npx`とは違って実行するパッケージはインストールされている必要があります。

まあ便利な`npm`という感じで私は使ってますね。

こちらも、一例を実行してみたので下記ご参照ください。

```
PS C:\Users\user\Desktop> yarn add envinfo
# npxとはみたいに実行できる
PS C:\Users\user\Desktop> yarn envinfo
  System:
    OS: Windows 10
    CPU: (4) x64 Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz
PS C:\Users\user\Desktop> yarn remove envinfo

# npxとは違って自動でパッケージはインストールしてくれない
PS C:\Users\user\Desktop> yarn envinfo
yarn run v1.15.2
error Command "envinfo" not found. 
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```

## Nuxtプロジェクトを構築してみよう

それでは、Nuxtプロジェクトを構築していきます。
任意の作業ディレクトリで下記を実行します。

```
PS C:\Users\user\Desktop\project> npx create-nuxt-app
```
実行するといくつか質問されます。私は下記のように回答しました。

```
? Project name dev
? Project description dev
? Use a custom server framework none
? Choose features to install Progressive Web App (PWA) Support, Axios
? Use a custom UI framework vuetify
? Use a custom test framework jest
? Choose rendering mode Single Page App
? Author name dev
? Choose a package manager yarn
```
選択肢について以下で補足したいと思います。

**? Use a custom server framework**
この選択では、バックエンドのフレームワーク(express等)を選ぶことができます。
今回、バックエンド側はFirebaseに任せてフロントエンド側のみ作る予定なので`none`にしました。

**? Choose features to install Progressive**
この選択では、使用したいモジュールを選択すれば一緒にインストールをしてくれます。
将来的に使うかもしれないと思い`PWA`と`Axios`を選択してます。
PWAというのは、WEBの技術(HTMLやJavascript)でネイティブアプリのような動作を可能にする仕組みのことです。
Axiosというのは、Promise ベースの HTTP クライアントです。RestAPIの実行とか利用できます。

**? Use a custom UI framework**
この選択では、UIのフレームワークを選ぶことができます。今回は`Vuetify`を選択しました。
`Vuetify`とは Vue.js 用のUIコンポーネントフレームワークです。
マテリアルデザイン(Googleが推奨するデザイン)の手法に基づいたコンポーネントを提供しています。
手軽にGoogleっぽいデザインな画面を実現できてしまいます。
Vuetifyのコンポーネントのドキュメント：[リンク](https://vuetifyjs.com/ja/components/api-explorer)

**? Use a custom test framework**
この選択では、テストフレームワークを選ぶことができます。今回は簡単でシンプルといわれる`jest`を選択しました。
ただ、今回の作業では使用していません。テストしてません。

**? Choose rendering mode**
この選択では、レンダリングモードを選ぶことができます。記事タイトルにも書きましたが`SPA`を選択してます。
今回なぜ`SPA`にしたのか明確な理由はありません。
ただ、`SPA`のほうがホスティング先が多くて楽そうと思ったくらいです。
Nuxtの場合だと`nuxt generate`というコマンドを実行するだけで静的ファイルが吐き出されます。
その静的ファイルをアップするだけで`GitHubPage`みたいなホスティング先にデプロイできます。
他のレンダリングモードとして`SSR`があります。
※`SSR`でデプロイする場合は Node.js の入ったレンダリングを行うためのサーバが必要になります。






## Nuxtを起動してみる

さて、無事にNuxtプロジェクトを生成することができました。
プロジェクトを作成した場所で`yarn dev`コマンドを実行してみましょう。

```
PS C:\Users\user\Desktop\project> yarn dev
```

実行する開発用サーバーが起動するので`http://localhost:3000/ `にアクセスして確認することができます。

## NuxtにTypeScriptを適用してみる

※今回は**Nuxt v2.9**での適用手順になります。それ以前のバージョンとは手順が異なります。
[公式ガイド](https://typescript.nuxtjs.org/guide/setup.html#installation)を参考に適用していきます。

現時点では、NuxtでTypeScriptを使うためには下記の手順を踏む必要があります。

まずは`@nuxt/typescript-build`というパッケージをプロジェクトにインストールしましょう。

```
PS C:\Users\user\Desktop\project> yarn add --dev @nuxt/typescript-build
```
`--dev`というオプションを付けています。
これは、`devDependencies`としてパッケージを追加する時に付与するオプションです。
開発時のみ該当のパッケージを使用したい時とかは`devDependencies`としてパッケージを追加するのが通例となっています。
`@nuxt/typescript-build`はNuxtでTypeScriptを使用するためのものであり開発時のみで十分です。
逆に開発時以外にも使用するパッケージ（express）などは、`dependencies`としてパッケージを追加します。

続いて、Nuxtで`@nuxt/typescript-build`をビルド専用モジュールとして使用したいので、`nuxt.config.js`に下記を追記します。

```nuxt.config.js
export default {
  buildModules: ['@nuxt/typescript-build']
}
```

続いて、`tsconfig.json`を新規に作成します。作成する場所はプロジェクト直下で大丈夫です。
`tsconfig.json`の内容は公式ガイドを参考にしましょう。

```
PS C:\Users\user\Desktop\project> vi tsconfig.json
```
```tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "esnext.asynciterable",
      "dom"
    ],
    "esModuleInterop": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },
    "types": [
      "@types/node",
      "@nuxt/types"
    ]
  },
  "exclude": [
    "node_modules"
  ]
}
```

続いて、`vue-property-decorator`というパッケージを追加しましょう。
`vue-property-decorator`はVueアプリを**クラススタイルで実装**を行う時によく使用されます。
また、TypeScriptでは**デコレータ**と呼ばれる既存の関数に対して処理の追加/変更を行う為の機能が用意されています。
`vue-property-decorator`を使用することでデコレータを用いたVueアプリの実装が可能になります。
詳しくは、[vue-property-decorator](https://www.npmjs.com/package/vue-property-decorator)のReadmeを読むことを推奨します。

```
PS C:\Users\user\Desktop\project> yarn add --dev vue-property-decorator
```
パッケージの追加が終わったら、先ほど用意した`tsconfig.json`の`compilerOptions`に下記を追記してあげましょう。

```tsconfig.json
{
  "compilerOptions": {
    "experimentalDecorators": true,
  }
}
```

最後にTypeScriptの書かれたソースコードがしっかりとビルドされるかの動作確認を行います。
先ほど自動生成されたNuxtプロジェクトの`pages/index.vue`を使って動作確認をしていきます。

```pages/index.vue
<script>
import Logo from '~/components/Logo.vue'
import VuetifyLogo from '~/components/VuetifyLogo.vue'

export default {
  components: {
    Logo,
    VuetifyLogo
  }
}
</script>
```
こちらは自動生成された時のIndexページのScript部分の抜粋です。
これをTypeScriptのクラスベースに書き換えていきましょう。

```pages/index.vue
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import Logo from '~/components/Logo.vue'
import VuetifyLogo from '~/components/VuetifyLogo.vue'

@Component({
  components: {
    Logo,
    VuetifyLogo
  }
})
export default class IndexPage extends Vue {}
</script>
```
IndexPageクラスという形でクラスベースに置き換えました。
アノテーションを使ってComponent定義を行っています。
作成するクラスには`vue-property-decorator`のVueクラスを忘れずに継承させましょう。

上記の状態でコンパイルが正常に実行されるか`yarn dev`で確認してみましょう。

```
PS C:\Users\user\Desktop\project> yarn dev
```
正常にコンパイルされたら`http://localhost:3000/`で画面を確認してみましょう。

以上が、TypeScriptを適用させる手順でした。

## ログインページを作成する
さて、一通り環境の構築を終えたところで実装に移っていきます。
`login.vue`というファイル名のログインページを`pages`の中に作りたいと思います。
ログイン認証処理は後述しますが、ひとまず見た目だけ作ってみます。

```pages/login.vue
<template>
  <v-form>
    <v-container>
      <v-text-field label="MailAddress" v-model="mail"></v-text-field>
      <v-text-field label="Password" v-model="pass"></v-text-field>
      <v-btn color="primary" @click="login">ログイン</v-btn>
    </v-container>
  </v-form>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'

@Component({
  layout: 'default',
  components: {
  }
})
export default class LoginPage extends Vue {
  mail: string = ''
  pass: string = ''

  login() {
    alert('Login !!')
  }
}
</script>
```
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/d401f067-7c84-d962-f3a8-1ef134337a2e.png)
良い感じにデザインもあたってくれて綺麗な画面が出来上がりました。
さらにこのページは`vue-property-decorator`を使用したクラスベースの実装にしています。
`v-model`で使用している`Data`はクラスメンバとして定義するだけで利用できます。
`@click`で使用している`methods`はクラスメソッドとして定義するだけで利用できます。

続いて、ログイン認証の実装部分に移りますが、ログイン認証には**Firebase**を利用します。
まずは動作確認用としてFirebase上にUserを追加していきましょう。
前述で作成したFirebaseプロジェクトのコンソールにアクセスします。

### Firebase上にUserを追加しておく
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/5bd6586f-88b0-011a-a9d0-a2afbce631d1.png)

上記の画面で`ログイン方法`を設定します。
今回は`メールアドレス`と`パスワード`の2つでログイン出来るように有効にしました。
メールリンクは無効のままにしています。
メールリンクログインというのは、認証リンクが記載された文面のあるメールをFirebaseがログイン対象のメールアドレス宛に送信します。
受信したメールを確認して認証リンクを踏むことでログイン認証が完了する仕組みになっております。

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/eb09af7b-5b45-b0ae-6ecb-de861ac049ae.png)

ログイン方法の設定が完了したら、上記の画面から動作確認用ユーザを追加しときましょう。

## firebaseログインの実装準備
Firebaseログイン実装に移る前に、プロジェクトにクライアント向けSDKをインストールしましょう。[公式リファレンス](https://firebase.google.com/docs/reference/js/?hl=ja)

```
PS C:\Users\user\Desktop\project> yarn add firebase
```

パッケージのインストールが完了したら、さっそく使っていきたいと思います。
どのコンポーネントからでも使用できるように、firebaseSDK呼び出し用プラグインでもplugins配下に作っておきましょう。

```plugins/firebase.ts
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'

// SDKを使用するためのConfig情報
const firebaseConfig = {
  apiKey: "xxxxxxxxxxx",
  authDomain: "xxxxxxxxxxx",
  databaseURL: "xxxxxxxxxxx",
  projectId: "xxxxxxxxxxx",
  storageBucket: "xxxxxxxxxxx",
  messagingSenderId: "xxxxxxxxxxx",
  appId: "xxxxxxxxxxx",
  measurementId: "xxxxxxxxxxx"
}
// Appの初期化
if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig)
}
// 今回使用するAPI
export const auth = firebase.auth()
export const firestore = firebase.firestore()
```
これで、使用したい場所で`import { auth } from 'plugins/firebase'`みたいに使えるようになりました。

**firebaseConfigってどこにあるの？**
SDKを使用する場合、事前にFirebaseプロジェクト内にアプリを追加しておく必要があります。
アプリの追加手順を以下にまとめます。

まずは、Firebaseプロジェクトのコンソールにいきましょう。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/67296b8c-70c7-dcd9-9976-45b9fe2230fb.png)
上記の画面で「</>」のボタンを押します。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/6920b427-2482-4272-0ce4-3a7622b00e2a.png)
次に、上記の画面でアプリのニックネームを決めてアプリの登録ボタンを押します。
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/49bc354f-56ca-845e-7d16-5c1d12240164.png)
今回はNPMを使うので、この画面はスルーで良いです。
![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/1aea0194-0aa4-b9cb-ba1c-e8ec4f0a304b.png)
この画面は、`firebase-tools`というパッケージをインストールする場合の手順が記載されています。
FirebaseにはHostingのサービスがあります。
`firebase-tools`はローカルからFirebaseへデプロイする時にポチポチする時に使ったりします。
今回はHostingをする予定がないので、スルーで良いです。
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/9ffaa6a7-406b-079c-cdc0-0555dbfd4708.png)
今回はHostingをする予定がないので、スルーで良いです。
![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/8f3b99db-0543-1a5e-6135-6e21cb525e46.png)
アプリの追加が終わったら、上記画面からFirebaseConfig情報をコピーすることが出来るようになりましたので、
先ほどの`plugins/firebase.ts`に貼り付けてやりましょう。

## firebaseログインの実装

では、Firebaseログインを実装します。
先ほど作成した`pages/login.vue`とレイアウトは変わらないで処理の部分だけ以下に載せます。

```pages/login.vue
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { auth } from '../plugins/firebase'

@Component({
  layout: 'default',
  components: {
  }
})
export default class LoginPage extends Vue {
  mail: string = ''
  pass: string = ''

  login() {
    auth.signInWithEmailAndPassword(this.mail, this.pass)
      .then(user => this.$router.push('/'))
      .catch(e => alert(e.message))
  }
}
</script>
```
たった3行でログイン処理を実装できてしまいました。
ログインに成功したらTopページへ遷移、失敗したらアラートでエラー内容を表示という実装になります。

次に、Topページにログアウト処理も作ってしまいます。

```pages/index.vue
<template>
  <v-container>
    <div v-if="isLogin"><v-btn @click="logout">ログアウト</v-btn></div>
  </v-container>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { auth } from '../plugins/firebase'

@Component({
  layout: 'default',
  components: {
  }
})
export default class IndexPage extends Vue {
  isLogin:boolean = false
  async mounted() {
    await auth.onAuthStateChanged((user) => this.isLogin = user ? true : false)
  }
  async logout() {
    await auth.signOut()
    this.$router.push('/login')
  }
}
</script>
```
上記の実装では、ログイン中かどうかを分かりやすくするために、ログイン認証済みの場合はログアウトボタンが出現するような仕組みにしています。
ログインしていれば、ログアウトボタンが表示されます。
ちなみに、`onAuthStateChanged`関数で、認証状態の変化を監視します。
認証されていれば、ログイン中の`user情報`を返します。

ただ、このままではログインしなくてもトップページへ遷移できてしまいますね。。。

さて、ログインしていない場合はTopページ（というか全てのページ）にアクセスできない仕組みを施します。
`middleware`配下に`auth.ts`(ファイル名は任意)を作成しましょう。

```middleware\auth.ts
import { Middleware } from '@nuxt/types'
import { auth } from '../plugins/firebase'

const middleware:Middleware = ({ route, store, redirect }) => {
  auth.onAuthStateChanged((user) => {
    if (! user && route.name !== 'login') redirect('/login')
  })
}
export default middleware
```
先ほどの`pages/index.vue`も`mounted`で実装していた内容に似ていますね。
ログインされていないかつアクセスされたURLが`/login`でない場合は強制的に`/login`へリダイレクトさせてます。
※先ほどの`pages/index.vue`に記載した`mounted`の内容はもう不要なので適宜消してしまってくださいね。

ただ、このままではミドルウェアが反映されません。
ミドルウェアの作成が終わったら`nuxt.config,js`に下記を追記してやります。

```nuxt.config.js
  router: {
    middleware: ['auth']
  },
```
これにより全てのページに対して`middlware/auth.ts`が適用されます。

以上、Firebaseログインの実装になります。


長くなってしまいましたが、Nuxt+Firebaseでのログイン処理実装でした。
ぜひ、参考にしていただければ幸いです！！