Firebase Javascript SDK v8→v9における進め方と注意事項
はじめに
自分のアプリで使用しているFirebase Javascript SDKをv8からv9(modular
方式)へ移行しました。その際につまづいた点がいくつかあったので、忘備録も兼ねて、進め方や注意点を整理しました。今回触れる機能は以下の通りとなります。
- Authentication
- Cloud Firestore
- Cloud Storage
- Cloud Functions
※ Modular
とCompat
の説明については公式のcompatライブラリについてを参照ください。
方針
基本的には公式のアップグレードガイドに従い進めることができます。compat
(v8と互換)と共存させながら段階的にmodular
へ移行することをお勧めします。以下のように両方の方式でFirebaseを初期化しておくことで、機能ごとに徐々に移行を進めることができます。
import firebase from "firebase/compat/app"
import { initializeApp } from "firebase/app"
// compat(v8互換)方式の初期化
firebase.initializeApp({ /* config */ });
// modular方式の初期化
const firebaseApp = initializeApp({ /* config */ });
export default firebaseApp;
たとえば認証はmodular
へ移行する一方で・・・
import firebaseApp from './initializeApp';
import { getAuth, onAuthStateChanged } from "firebase/auth";
const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
// Check for user status
});
Firestoreはv8互換のままとしたい(既存の書き方を変更しない)
import firebase from "firebase/compat/app"
import "firebase/compat/firestore"
const db = firebase.firestore();
// 以降、既存のコードのまま
・・・
といった進め方をすることができます。
(自分の場合は一旦全てをcompat
に置き換えて、一つずつmodular
に移行しました)
Modularへの置き換え
各機能を順にmodular
に置き換えていきます
Authentication / Cloud Functions
公式(Authentication/ Cloud Functions)のページにmodular
スタイルの記法が載っており、こちらを参考に書き直していくことで比較的スムーズに移行を進めることができます。
AuthenticationやCloud FunctionsについてはFireStoreなどと比べて比較的単純な置き換えで済むため、modular
への移行の手始めとするのが良いかと思います。
FireStore
こちらも公式のFireStoreに従い、各メソッドを修正することでスムーズに進めることができます。但し、Firestoreの場合は長いドットチェーンをmodularに変更しないといけないケースがあるため、以下のように適切なヘルパー関数を使って読みやすくすることをお勧めします。
// ヘルパー:RoomのサブコレクションであるMessagesコレクションを取得する
const getMessageCollection = (roomId: string) =>
collection(doc(collection(firestore, 'rooms'), roomId), 'messages')
...
// 呼び出し側
addDoc(
getMessageCollection(roomId),
newMessageData
).then((result) => {
//省略
})
注意事項
exists
プロパティを用いて以下のような処理を行なっている場合に少し注意が必要です
docRef.get().then((doc) => {
if (doc.exists) { // ←v8でこの処理を記述をしている場合は注意
// ドキュメントが存在する場合の処理
} else {
// ドキュメントが存在しない場合の処理
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
exists
プロパティはexists()
メソッドに置き換わっており、then
以降をv8の書き方で踏襲しようとした場合、ドキュメントの存在有無に関わらず、常にif文がtrueに評価されてしまう状況に陥ります(文法自体に問題はないためビルドエラーをすり抜けてしまう)。以下のように修正を行う必要があります
getDoc(doc(db, "cities", "SF")).then((doc) => {
if (doc.exists()) { // ←気付きにくいが、メソッドに変更する必要あり
// ドキュメントが存在する場合の処理
} else {
// ドキュメントが存在しない場合の処理
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
(自分の場合はこの変更に気づかず、調査に結構な時間を費やしてしまいました・・・😢)
Storage
Storageは2021/9時点で日本語ドキュメントにv9の記載がありません。ただし、言語を英語にすることでv9の記述を確認することができます。
child
がなくなっていたり、使い方が割と変更されていますが、基本的に公式ドキュメントに記載の通りに修正していけば問題はないはずです。
最後に
各機能の移行が無事済んだら、最後に初期化のcompat
コードを削除します
- import firebase from "firebase/compat/app"
import { initializeApp } from "firebase/app"
- // compat(v8互換)方式の初期化
- firebase.initializeApp({ /* config */ });
// modular方式の初期化
const firebaseApp = initializeApp({ /* config */ });
export default firebaseApp;
modular
に移行するには結構なリファクタリングが必要となりますが、今まで結構なサイズを占めていたFirebaseのバンドルサイズが大きく削減することができるので、苦労に見合うメリットはあるかと思います。
Discussion