Firebase v9 + Vue3 + Vite + Vuetify3 beta で firebase auth のメール認証でログインしてみるの、TypeScript版
元のQiita:Firebase v9 + Vue3 + Vite + Vuetify3 beta で firebase auth のメール認証でログインしてみる をTypeScript版でうまくいくようにやってみましょうという事です。
ちなみに筆者は、Vue2とVuetify2を少し触ってたら、時代がVue3になっていて驚いている人、世間様があまりにもTypeScriptというもんだから、TypeScriptを学習初めたばかりのものです。つまりはどちらも慣れてはおりません。これから学んで慣れていければと思っております。
変更した所のまとめ
js | ts | |
---|---|---|
アプリ作成 | vue-create app | yarn create vite |
vue-routerインストール | vue add router | yarn add vue-router@4 |
各種ファイル | firebase.js, router.js | firebase.ts, router.ts |
Vue関連のインストール
Vue3のアプリの作成
参考:Vite + Vue3にESLintとPrettierを導入する
vue-createでなく、yarn create viteを使う
yarn create vite
? Project name: vue-ts-app
? Select a framework > vue
? Select a variant > vue-ts
cd vue-ts-app
yarn
yarn dev
Vuetify3の追加
vue add vuetify
? Choose a preset: > Vite Preview (Vuetify 3 + Vite)
yarn dev
Welcome to Vuetify 3 Beta Vite Previewというページを見ることができました。
vue-routerのインストール
参考:Vue3 + TypeScript + Vue RouterからはじめるWebアプリケーション開発
vue add router
は使わない
yarn add vue-router@4
yarn以外のパッケージマネージャーを使うと
-
npm
を使った場合、vue add vuetify
後は、なぜかnpm install がエラーとなる場合がありました。 -
pnpm
だとvue add vuetify
自体でエラーが出てしまいそこから進めなくなりました。他のvue add
でも同様とのIssueがあがっていました。 - すべて
vue add
が鬼門のもようです。
routerの設定
src/router.tsの作成
ViteのCLIがrouterをインストールしたら色々設定してくれるということは無いので、色々手作業で設定する必要があります。
ここでは、'/'にアクセスされると、現在はまだ存在しないファイルsrc/views/HomeView.vueを読むという設定にしています。
参考:Vite で作成したアプリのVue-routerの設定方法
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'home',
component: () => import('./views/HomeView.vue'),
},
]
const router = createRouter({
history: createWebHistory(), // HTML5 History モード
routes,
})
export default router
src/main.tsに追加する
import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import { loadFonts } from './plugins/webfontloader'
import router from './router' // この行を追加
loadFonts()
// ここらへ.use(router)を追加
createApp(App)
.use(vuetify)
.use(router)
.mount('#app')
App.vueの変更
routerで飛ばされるだけの存在にしてみます。
<template>
<v-app>
<router-view />
</v-app>
</template>
src/views/HomeView.vueを作る
mkdir -p src/views
<template>
<v-app>HOME(HomeView)</v-app>
</template>
routerの動作確認
yarn dev
出てきたリンクにアクセスしてHOME(HomeView)のみ表示されるシンプルなものが見えたら動作確認完了です。
firebase
初期化
firebase initして、必要なサービスを選び、Firebaseのプロジェクトに紐付ける。そしてそのプロジェクトでは、initした時に選択したサービスはFirebase consoleで開始しておく必要がある。Authenticationではログインプロバイダで、メール/パスワードは使えるようにしておく必要がありました。
firebase init
? Which Firebase features do you want to set up for this directory?...
Hosting: Set up GitHub Action deploys以外を全部選択してみました
? Please select an option: > Use an existing project
? Select a default Firebase project for this directory: vue3ts-123456 (Vue3ts)
? What file should be used for Realtime Database Security Rules? database.rules.json
? What file should be used for Firestore Rules? firestore.rules
? What file should be used for Firestore indexes? firestore.indexes.json
? What language would you like to use to write Cloud Functions? TypeScript
? Do you want to use ESLint to catch probable bugs and enforce style? Yes
? Do you want to install dependencies with npm now? Yes
Hosting Setupの? What do you want to use as your public directory? だけはデフォルトとは全然違う回答をしているので注意、distにしています。
Emulators Setupは全部選択しました。
Emulatorsのportは全部デフォルトでエンターを押しました
? What do you want to use as your public directory? dist
? Configure as a single-page app (rewrite all urls to /index.html)? No
? Set up automatic builds and deploys with GitHub? No
? What file should be used for Storage Rules? storage.rules
? Which Firebase emulators do you want to set up? Press Space to select emulators, then Enter to confirm your choices. 全部
EmulatorsのPortは全部デフォルトに
? Would you like to enable the Emulator UI? Yes
? Which port do you want to use for the Emulator UI (leave empty to use any available port)?
? Would you like to download the emulators now? No
? What file should be used for your Remote Config template? remoteconfig.template.json
APIキーなどの登録
環境変数を使う
参考:【Vue.js】VueCLI3.x 4.xで環境変数を扱う場合は .env ファイルに VUE_APP_ の接頭語をつける
-
プロジェクトルートに.env.localというファイルを作成し、そこに環境変数を書きFirebaseのAPIキーなど、外部に渡したくないものを書くと、Vue3は自動的に.env.localを読み込み、環境変数に設定しました。
-
環境変数の接頭辞はVUE_APP_としないと読み込みません。
-
.env.localファイルを.gitignoreに登録しました。
この辺りを手で書いても良いのですがそれを楽にするツールを使うことにします。firebaseで使うプロジェクトから、web app's Firebase configurationをコピーまたはファイルに保存します。
そして、npmによるcliツール@hkj_50/firebase-configを実行して質問に答え、src/firebase.tsと.env.localファイルを生成します。
npx @hkj_50/firebase-Config
? Where is the root dir of the your App? ./
? Enviroment Variables file name? .env.local
? Do you use firebase's emulator? Yes
? In which format should the contents of firebaseConfig be entered? file
? Where is the path to the file containing firebaseConfig? ../firebaseConfig.js
上記の場合は、プロジェクトルート上でnpx @hkj_50/firebase-config
を実行し、web app's Firebase configurationを../firebaseConfig.js
という名前で保存していたので、それを指定しています。エミュレータを使うと指定しました。その結果、src/firebase.ts
と.env.local
という二つのファイルが生成されました。
import { initializeApp } from 'firebase/app';
import { getFunctions, connectFunctionsEmulator } from "firebase/functions";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import { getStorage, connectStorageEmulator } from "firebase/storage";
import { getAuth, connectAuthEmulator } from "firebase/auth";
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: 'process.env.VUE_APP_API_KEY',
authDomain: 'process.env.VUE_APP_AUTH_DOMAIN',
databaseURL: 'process.env.VUE_APP_DATABASE_URL',
projectId: 'process.env.VUE_APP_PROJECT_ID',
storageBucket: 'process.env.VUE_APP_STORAGE_BUCKET',
messagingSenderId: 'process.env.VUE_APP_MESSAGING_SENDER_ID',
appId: 'process.env.VUE_APP_APP_ID',
}
const firebase = initializeApp(firebaseConfig);
const isEmulating = window.location.hostname === "localhost";
if (isEmulating) {
const auth = getAuth();
connectAuthEmulator(auth, "http://localhost:9099");
const storage = getStorage();
connectStorageEmulator(storage, "localhost", 9199);
const db = getFirestore(firebase);
connectFirestoreEmulator(db, 'localhost', 8080);
const functions = getFunctions(firebase);
connectFunctionsEmulator(functions, "localhost", 5001);
}
export const firebaseApp = () => { return firebase };
export default firebase;
肝心な情報は環境変数から読み込まれ、このファイルには書かれていないので、gitに含めたり、githubにて公開されても問題ありません。
VUE_APP_API_KEY="YourApiKey"
VUE_APP_AUTH_DOMAIN="yourAuthDomain.firebaseapp.com"
VUE_APP_DATABASE_URL="https://yourdomain.firebaseio.com"
VUE_APP_PROJECT_ID="yourID-12345"
VUE_APP_STORAGE_BUCKET="youID-12345.appspot.com"
VUE_APP_MESSAGING_SENDER_ID="123456789012"
VUE_APP_APP_ID="1:123456789012:web:a11bbcc123456ab1a1b23b"
こちらは肝心な情報なので、.gitignoreに入っていない場合は登録します。
echo '*.local' >> .gitignore
tsconfig.jsonの設定
参考:TypeScript に対応した Vue 3 プロジェクト の作成
その項目が無ければ、"compilerOptions"以下に、"baseUrl"と"paths"の設定を追加します。
{
"compilerOptions": {
...
...
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
...
...
}
firebase関連のインストール
yarn add firebase
確かにこれは忘れやすいと、私も思いました。
src/App.vueにfirebaseApp登録を追加
<template>
<v-app>
<router-view/>
</v-app>
</template>
<script setup lang="ts">
import { firebaseApp } from './firebase';
const app = firebaseApp()
</script>
このfirebaseApp()を呼ばないとfirebaseを初期化していないと怒られる現象が後に起こります。
Firebaseを使った機能の実装例
Homeview.vueに実装してみます。元々の書き方がComposition APIっぽくない書き方をしていたので、Composition API風に書き替えています。<script setup lang>
を使う事によって、余計な呪文を排除して、scriptとtemplateとstyleのみとなったすっきりした書き方ができるようになります。
Refで動的に変更する変数を定義します。constで定義していますが、refのオブジェクトになり、変数.valueという形で実際の値を使い、そのvalueは変更可能です。
mounted()はonMounted()内に書きます。
v-if="currenUser.value === null"と書きたかったのですが、nullである可能性があるとなってエラーとなりました。v-if="currentUser === null"であれば、エラーとならず、動作の目的には叶いました。しかし、本当にこれで良いのかは良く分かっておりません。
<script setup lang="ts">
import { ref, Ref, onMounted } from 'vue'
import {
getAuth,
signOut,
onAuthStateChanged,
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
User,
} from 'firebase/auth'
const emailText: Ref<string> = ref('')
const passwordText: Ref<string> = ref('')
const message: Ref<string> = ref('')
const currentUser: Ref<User | null> = ref(null)
onMounted(() => {
const auth = getAuth()
onAuthStateChanged(auth, (user) => {
if (user != null) {
currentUser.value = user
} else {
currentUser.value = null
}
})
})
const signIn = () => {
// エラーなどメッセージをクリア
message.value = ''
if (emailText.value == '' || passwordText.value == '') return
const auth = getAuth()
signInWithEmailAndPassword(auth, emailText.value, passwordText.value)
.then((userCredential) => {
// Sign In
const user: User = userCredential.user
console.log(user)
})
.catch((error) => {
message.value = error.message
console.log(error.code, error.message)
})
}
const createAccount = () => {
message.value = ''
if (emailText.value == '' || passwordText.value == '') return
const auth = getAuth()
createUserWithEmailAndPassword(auth, emailText.value, passwordText.value)
.then((userCredential) => {
const user: User = userCredential.user
console.log(user)
})
.catch((error) => {
message.value = error.message
console.log(error.code, error.message)
})
}
const logOut = () => {
const auth = getAuth()
signOut(auth)
.then(() => {
currentUser.value = null
})
.catch((error): void => {
console.log(error)
})
}
</script>
<template>
<v-container>
<div v-if="currentUser === null">
<v-card width="400px" class="mx-auto mt-5">
<v-card-actions>
<v-col>
<v-text-field
v-model="emailText"
label="E-MAIL"
>
</v-text-field>
<v-text-field
v-model="passwordText"
label="PASSWORD"
type="password"
>
</v-text-field>
<v-btn @click="signIn" color="primary"> E-Mail Sign In </v-btn>
<v-btn color="primary" @click="createAccount">Sign Up</v-btn>
<div class="message">{{ message }}</div>
</v-col>
</v-card-actions>
</v-card>
</div>
<div v-else>
<h2>Success to sign in with firebase auth!</h2>
<v-btn @click="logOut">Sign Out</v-btn>
</div>
</v-container>
</template>
<style scoped>
.message {
color: red;
}
</style>
Functionsの設定
必要なライブラリが入ってないのとビルドがされていないので実行
cd functions
yarn
yarn build
buildで
rc/index.ts:1:1 - error TS6133: 'functions' is declared but its value is never read.
1 import * as functions from "firebase-functions";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
と怒られました。現時点ではfunctionsは使わないので、コメントアウトしておきます。
// import * as functions from "firebase-functions";
そこで再びbuild
yarn build
エラーが出ずに完了しました。
Firebase Emulatorの実行と確認
firebase emulators:start
とやってから違うターミナルで
yarn dev
とやってください。E-MAILとPASSWORDの所に入れて初めてであれば、SIGN UP、そうでなければ、E-MAIL SIGN INを選んでいただいて、Success to sign in with firebase auth!
と出て、SIGN OUTボタンを押せば元に戻れば成功です。