TechVue.jsGCP-FirebaseJapanese

Vue3 + TypeScript プロジェクト から Firestore に接続する サンプル

Tech

Vue3 + TypeScript プロジェクト で Firebase の リアルタイム DB である Firestore に アクセス して データ を取得する サンプル を紹介します。 本記事では、事前に Firestore に格納しておいた データ を Vue アプリケーション で表示してみようと思います。 なお、 今回は例として、開発環境で実装していきます。

vue: 3.2.33
firebase: 9.6.11
firebase-admin: 10.1.0

準備

[ads]

Firestore に作成済みの データ

Firestore には 以下のようなデータを作成してあります。 この データ を Vue プロジェクト で読み出して 画面に表示する アプリケーション を作っていきます。

Collection: users
Document: alovelace
Data:
    born: 1815
    first: “Ada”
    last: “Lovelace”

プロジェクト作成 (Vue3 + TypeScript)

まずは、Vue3 + Typescript でプロジェクトを作成します。

npm init [email protected]

Vue3 プロジェクト に Firebase SDK を インストール

以下の コマンド で Firebase SDK を インストール していきます。

npm install --save firebase-admin
npm install firebase

Firebase 接続設定情報 を Vite 環境変数に登録

Firebase に接続するためには API Key などの接続設定情報が必要になります。 これらの取得方法については 公式サイト を参照してください。この 接続設定情報 を Firebase SDK に渡すことで、Vue プロジェクト から Firebase に アクセス することができるようになります。

このように Firebase への アクセス は簡単に実現できるのですが、 逆に言うと、これらの接続設定情報 を悪用されてしまうと、第三者が簡単にあなたの課金設定済みアカウントを用いることもできてしまいます。そういった事態を避けるためにも、 Firebase 接続設定情報 は git に登録しないことが望ましいケースが多いと思います。 ここでは .local.development.local ファイル に Firebase 接続設定情報 を記載し、この問題に対処することにします。

プロジェクト の ルートディレクトリ に .env.development.local ファイル を作成し、以下の項目を用意し、該当する値を記載し保存します。

VITE_FB_APIKEY=
VITE_FB_AUTHDOMAIN=
VITE_FB_PROJECTID=
VITE_FB_STORAGEBUCKET=
VITE_FB_MESSAGINGSENDERID=
VITE_FB_APPID=

拡張子に .local を採用していることで、git から除外されることになることが確認できるはずです。 .gitignore ファイル に以下の記載があることで確認することができます。

*.local

実装

[ads]

Fireabase 接続処理の作成 (FirebaseConfig.ts)

環境変数に Firebase 接続設定情報 を登録できましたので、次に Firebase の接続処理を作成していきます。 main.ts と同じ ディレクトリ に FirebaseConfig.ts を作成します。 ここでは、以下の処理を実施します。

  • 環境変数から Firebase 接続設定情報 を読み込む
  • firebase/app の initializeApp を用いて Firebase プロジェクトに接続
  • Firebase プロジェクト に存在する Firestore に接続
  • コンポーネント では 必要に応じて firebase/firestore モジュール をインポートする (collection, getDocs 等)
import { initializeApp } from 'firebase/app'
import { getFirestore } from 'firebase/firestore'

const config = {
    apiKey: import.meta.env.VITE_FB_APIKEY,
    authDomain: import.meta.env.VITE_FB_AUTHDOMAIN,
    databaseURL: import.meta.env.BASE_URL,
    projectId: import.meta.env.VITE_FB_PROJECTID,
    storageBucket: import.meta.env.VITE_FB_STORAGEBUCKET,
    messagingSenderId: import.meta.env.VITE_FB_MESSAGINGSENDERID,
    appId: import.meta.env.VITE_FB_APPID,
}

export const app = initializeApp(config)
export const db = getFirestore(app)

Vue コンポーネント で Firestore の情報を取得

[ads]

ここまでの作業で Vue3 プロジェクト から Firestore に接続する準備が完了しました。 最後に Vue コンポーネント から 実際にこの処理を用いて Firestore に接続してみたいと思います。
今回は MyFirebase.vue という コンポーネント を作成して そこに実装していきます。

Firebase から取得した データ 格納用の変数等の準備

まずは、 Firestore から取得した データ を格納する変数などを準備していきます。

  • Firestore から 取得した データ 格納用の ref 変数 の data
  • Firestore から データ を取得する処理の getUsers を async 関数として定義
  • アプリ マウント時に Firestore に接続するために onMounted を用意
<script setup lang="ts">
import { ref, onMounted } from 'vue'

const data = ref()

const getUsers = async () => {
    console.log("getUsers")
}

onMounted(() => {
    getUsers()
})

</script>

Firestore からの データ 取得処理実装

先ほど、外側だけ作った getUsers の中身を作成していきいます。

  • インポート
    • Firebase からの データ 取得処理 モジュール collection, getDocs
    • 事前に作成した Firebase 接続処理 firebaseConfig から db オブジェクト
  • 変数作成
    • Firebase からの 応答を待っていることを示す ref 変数 の isLoading
    • 接続時の エラー を格納する ref 変数 の error
  • Firebase からの データ 取得処理は こちら を参考に実装
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { collection, getDocs } from 'firebase/firestore'
import { db } from '../firebaseConfig'

const data = ref()
const isLoading = ref(false)
const error = ref()

const getUsers = async () => {
    console.log("getUsers")
    isLoading.value = true
    try {
        const usersCollection = collection(db, 'users');
        const usersSnapshot = await getDocs(usersCollection);
        data.value = usersSnapshot.docs.map(doc => doc.data());
        console.log(data.value)
    } catch (e) {
        error.value = e
    } finally {
        isLoading.value = false
    }
}

onMounted(() => {
    getUsers()
})

</script>

UI の実装

最後に UI を実装していきます。

  • v-if を使って データ 取得中 は Loading… を表示
<template>
    <div>
        <h1>My Firebase</h1>
        <div v-if="isLoading">Loading...</div>
        <div v-else>{{ data }}</div>
    </div>
</template>

実行

[ads]

それでは、ここまで作ってきた Vue3 プロジェクト を 実行してみます。

npm run dev

アプリケーション を起動すると 最初に “Loading…” の文言が表示されますが、 その後 無事 Firestore に格納された目的のデータを取得し、表示することができました。


まとめ

[ads]
  • Firebase SDK に渡す API Key などは ソースコード に直接記載するのではなく、 環境変数を用いるなどで ソースコード 管理外とするのがベター
  • 接続処理をfirebaseConfig.ts などで 記載し DB オブジェクト を エクスポート しておく
  • Firebase に接続する コンポーネント で エクスポート された DB オブジェクト をインポート して利用する

関連記事

[ads]

今回使用したコード

firebaseConfig.ts

import { initializeApp } from 'firebase/app'
import { getFirestore } from 'firebase/firestore'

const config = {
    apiKey: import.meta.env.VITE_FB_APIKEY,
    authDomain: import.meta.env.VITE_FB_AUTHDOMAIN,
    databaseURL: import.meta.env.BASE_URL,
    projectId: import.meta.env.VITE_FB_PROJECTID,
    storageBucket: import.meta.env.VITE_FB_STORAGEBUCKET,
    messagingSenderId: import.meta.env.VITE_FB_MESSAGINGSENDERID,
    appId: import.meta.env.VITE_FB_APPID,
}

export const app = initializeApp(config)
export const db = getFirestore(app)

App.vue

<script setup lang="ts">
import MyFirebase from './components/MyFirebase.vue'
</script>

<template>
  <div>
    <MyFirebase />
  </div>
</template>
[ads]

MyFirebase.vue

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { collection, getDocs } from 'firebase/firestore'
import { db } from '../firebaseConfig'


const data = ref()
const isLoading = ref(false)
const error = ref()

const getUsers = async () => {
    console.log("getUsers")
    isLoading.value = true
    try {
        const usersCollection = collection(db, 'users');
        const usersSnapshot = await getDocs(usersCollection);
        data.value = usersSnapshot.docs.map(doc => doc.data());
        console.log(data.value)
    } catch (e) {
        error.value = e
    } finally {
        isLoading.value = false
    }
}

onMounted(() => {
    getUsers()
})

</script>
<template>
    <div>
        <h1>My Firebase</h1>
        <div v-if="isLoading">Loading...</div>
        <div v-else>{{ data }}</div>
    </div>
</template>

Ads
Rambling and Delving