Firebaseの初期化でめちゃくちゃハマったのでメモ。
ネット上をさまよったが、どうもFirebaseの新旧のバージョンで書き方が変わったため、かなり情報がごちゃごちゃになってるっぽい。
環境
- Windows10
- TypeScript 3.3.3
- Vue CLI 4.2.2
- firebase モジュール ^7.12.0
プロジェクトの生成等は次のとおり。
vue create <project>でテンプレート生成firebase initでVue ProjectにFirebase Hostingを設定npm i firebaseでfirebaseモジュールをインストール
とまあ、デプロイ用にFirebase Hostingのみ用意した。 一応エディタはVSCode使用です。
何ができなかったのか
firebase.auth is not a functionエラーが頻発し匿名認証ができないnpm run serveした場合は、認証もとおるしfirebase.storageでファイルアップロードもできる- 一方で
firebase serveした場合は、not a functionエラーにより認証ができない
なぜnpm run serveした方が認証もうまく行くのかはいまだに謎だが、
そもそも初期化の仕方がよく分かっていなかった。
何が原因だったか
コード上でfirebase.initializeAppを実行しつつ、HTML上でも<script ~~~ /firebase/init.js ~~~></script>を読み込んでたのがだめだったっぽい。
できればコード上で完結したかったので、init.jsの行は削除した。
ついでに読み込んでたライブラリ群<script ~~~/firebase-auth.js~~~>や<script ~~~/firebase-storage.js>等も削除した。
どうやって解決したか
上で書いたとおり、コード上で初期化する形に寄せてみた。
なおドキュメントでは<body>タグ内に書き込む方法が推しっぽいが、どうやってもうまくいかないので諦め。
コード上でFirebaseを初期化する
Firebaseコンソールでプロジェクトが作成されているものとして、
下記の場所からfirebaseConfigをコピーする。

次にVueプロジェクトフォルダのsrc配下にFirebaseConfig.ts等適当なtsファイルを作って貼り付ける。
FirebaseConfig.tsは公開しても全然美味しくないので、.gitignoreに追加しておく。
// FirebaseConfig.ts const conf = { // 構成をペースト }
main.tsで次のように初期化する。
// main.ts // @はsrcディレクトリのエイリアス ... import { conf } from '@/firebaseConfig.ts' import firebase from 'firebase/app' ... Vue.config.productionTip = false // Firebaseの構成を読み込んで初期化 firebase.initializeApp(conf) new Vue({ router, store, vuetify, render: h => h(App) }).$mount('#app')
次に、Firebase AuthだったりStorageを使用するVueコンポーネントで、 必要なパッケージをインポートする。
ここでは、適当にExample.vueをcomponentsディレクトリ配下に作ってやった。
// Example.vue
// Vuetifyのv-file-inputコンポーネントを使用
// Firebase Storageへのファイルのアップロードを想定
<template>
<v-app>
<v-content>
<v-file-input
color="primary"
@change="fileUpload">FileUpload</v-file-input>
</v-content>
</v-app>
</template>
<script lang="ts">
// firebase/authやfirebase/storageなど、必要なパッケージをインポート
import Vue from 'vue'
import * as firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/storage'
export default Vue.extend({
data: () => ({
}),
methods: {
// file-inputのイベントでfileUploadメソッドをコール
// 引数はany型。仕方ないね(何
fileUpload: (e: any) => {
// 匿名で認証しStorageにファイルをputする
firebase.auth().signInAnonymously().then(() => {
// Storageにsampleバケットを作っておき、とりあえずファイル名で参照を生成する
const sampleRef = firebase.storage().ref().child(`sample/${e.name}`)
// 生成した参照先にファイルをput
sampleRef.put(e).then(snapshot => {
// アップロード後の参照先はfullPathプロパティで確認可能
console.log(snapshot.ref.fullPath)
}).catch(err => {
console.error(err)
})
})
}
}
})
</script>
あとはExample.vueを適切に読み込んでやる(省略)。
ビルドしてfirebase serveで動作確認してアップロードできればおk
所感
どうやってもbodyタグに埋め込む方法がわからない。
/firebase/init.jsで初期化するとか言っててfirebase.initializeApp外すとエラー吐くし……。
まあ実際のところ、今後Firebaseの実装を隠ぺいする(interfaceをかませる)場合にコード上で制御できるほうが都合いいだろうし、今のところ支障はない。 だけど、できないのは気持ち悪いので機会があれば調べてみる。
npm run serve (Vue CLIでのserve)とfirebase serveとで動作違うのなんなのマジで……。