Firebaseの初期化でハマった
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
とで動作違うのなんなのマジで……。