はじめに
今回は、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)
さらに、Nuxtはサーバーミドルウェアを構築できたりします。
外部サーバを用意せずにJavascriptでAPIを用意したい時なんかはNuxtだけで実現できてしまいます。
Firebaseを選択する
Firebaseとは、言わずと知れたGoogleが提供しているWebアプリケーションのバックエンドサービスですね。
ドキュメントも分かりやすく、流行りのサーバレスアーキテクチャを学習コストほぼなしで実現できちゃいます。
サーバレスアーキテクチャってのはバックエンド系は任せちゃうやつです。
例えば、Web開発を行っていくうえで、NodeJSやPHP,Pythonを使ってDB操作や認証処理とかをバックエンド側として実装したりしますね。(DBを自前で用意してModel作って、、、リクエストされたpayloadからトークン発行して、、、などのアレです。)
アレをやらなくて済みます。
準備
Firebaseを始めてみる
まずはGoogleのアカウントを用意しましょう。
用意ができたら、Firebase Consoleへアクセスします。
上記の画面を確認したら、プロジェクトを作成を押します。
上記の画面では、適当なプロジェクト名を入力して規約同意にチェックして続行を押します。
上記の画面は、Googleアナリティクスを有効にするかどうかです。チェックして続行を押します。
先ほどの画面で、Googleアナリティクスを有効にチェックをしました。
そのため、アナリティクス対象の地域を選択したり、分析データの共有同意を求められます。
チェックしてプロジェクトを作成ボタンを押します。
少し時間が経つとプロジェクトが作成されます。続行を押します。
無事にプロジェクトの作成が終わりました。
Firebase Consoleからいつでも入れます。
※Googleアナリティクス
プロジェクト作成中にあったGoogleアナリティクスについてですが、
有効にしておくとアプリの使用状況とユーザーエンゲージメントについて分析できたりします。
ユーザの行動を把握してアプリのマーケティング方法の決定を決めるのに利用したり出来るようですね。
私はマーケティング経験も知識もないので使い道は良く知りませんが。。
Nuxtを始めてみる
$ npx create-nuxt-app <project-name>
# もしくは
$ yarn create nuxt-app <project-name>
公式を見ると上のコマンドで始められるとあります。
ローカルの環境に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のコンポーネントのドキュメント:リンク
? 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での適用手順になります。それ以前のバージョンとは手順が異なります。
公式ガイドを参考に適用していきます。
現時点では、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
に下記を追記します。
export default {
buildModules: ['@nuxt/typescript-build']
}
続いて、tsconfig.json
を新規に作成します。作成する場所はプロジェクト直下で大丈夫です。
tsconfig.json
の内容は公式ガイドを参考にしましょう。
PS C:\Users\user\Desktop\project> vi 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のReadmeを読むことを推奨します。
PS C:\Users\user\Desktop\project> yarn add --dev vue-property-decorator
パッケージの追加が終わったら、先ほど用意したtsconfig.json
のcompilerOptions
に下記を追記してあげましょう。
{
"compilerOptions": {
"experimentalDecorators": true,
}
}
最後にTypeScriptの書かれたソースコードがしっかりとビルドされるかの動作確認を行います。
先ほど自動生成されたNuxtプロジェクトの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のクラスベースに書き換えていきましょう。
<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
の中に作りたいと思います。
ログイン認証処理は後述しますが、ひとまず見た目だけ作ってみます。
<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>
良い感じにデザインもあたってくれて綺麗な画面が出来上がりました。
さらにこのページはvue-property-decorator
を使用したクラスベースの実装にしています。
v-model
で使用しているData
はクラスメンバとして定義するだけで利用できます。
@click
で使用しているmethods
はクラスメソッドとして定義するだけで利用できます。
続いて、ログイン認証の実装部分に移りますが、ログイン認証にはFirebaseを利用します。
まずは動作確認用としてFirebase上にUserを追加していきましょう。
前述で作成したFirebaseプロジェクトのコンソールにアクセスします。
Firebase上にUserを追加しておく
上記の画面でログイン方法
を設定します。
今回はメールアドレス
とパスワード
の2つでログイン出来るように有効にしました。
メールリンクは無効のままにしています。
メールリンクログインというのは、認証リンクが記載された文面のあるメールをFirebaseがログイン対象のメールアドレス宛に送信します。
受信したメールを確認して認証リンクを踏むことでログイン認証が完了する仕組みになっております。
ログイン方法の設定が完了したら、上記の画面から動作確認用ユーザを追加しときましょう。
firebaseログインの実装準備
Firebaseログイン実装に移る前に、プロジェクトにクライアント向けSDKをインストールしましょう。公式リファレンス
PS C:\Users\user\Desktop\project> yarn add firebase
パッケージのインストールが完了したら、さっそく使っていきたいと思います。
どのコンポーネントからでも使用できるように、firebaseSDK呼び出し用プラグインでもplugins配下に作っておきましょう。
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プロジェクトのコンソールにいきましょう。
上記の画面で「>」のボタンを押します。
次に、上記の画面でアプリのニックネームを決めてアプリの登録ボタンを押します。
今回はNPMを使うので、この画面はスルーで良いです。
この画面は、firebase-tools
というパッケージをインストールする場合の手順が記載されています。
FirebaseにはHostingのサービスがあります。
firebase-tools
はローカルからFirebaseへデプロイする時にポチポチする時に使ったりします。
今回はHostingをする予定がないので、スルーで良いです。
今回はHostingをする予定がないので、スルーで良いです。
アプリの追加が終わったら、上記画面からFirebaseConfig情報をコピーすることが出来るようになりましたので、
先ほどのplugins/firebase.ts
に貼り付けてやりましょう。
firebaseログインの実装
では、Firebaseログインを実装します。
先ほど作成した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ページにログアウト処理も作ってしまいます。
<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
(ファイル名は任意)を作成しましょう。
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
に下記を追記してやります。
router: {
middleware: ['auth']
},
これにより全てのページに対してmiddlware/auth.ts
が適用されます。
以上、Firebaseログインの実装になります。
長くなってしまいましたが、Nuxt+Firebaseでのログイン処理実装でした。
ぜひ、参考にしていただければ幸いです!!