2022.07.30

Firebaseのバージョンをv9に上げる

メンヘラテクノロジーのプロダクトはバックエンド(?)は基本的にFirebaseを使っています<br> Firebase JavaScript SDK (v9.0.0)が2021年の8月にリリースされてもうすぐ1年経ちそうですが、弊社でもついにv9への書き換えが行われました<br> 今回はその移行作業の記録を書きます

モチベーション

今回の作業を行おうと思った理由は2つあります<br> 1つ目はFirebaseの公式としては将来的にv10かv11あたりでv8の互換ライブラリを完全に削除することが決まっているそうなので、ずっとやらないといけないなという気持ちがありました<br> 2つ目はバンドルサイズを小さくしたいという課題がありました

v8以前とv9での違い

Firebaseはv8以前とv9での大きな違いとして、v9では”必要なものだけをインポートする”方式になりました<br> v8では import firebase from 'firebase/app' というように一旦すべてimportしていたのに対し、v9ではmodular形式になり、 import { initializeApp } from 'firebase/app' というような形で必要なものだけをimportするようになりました<br> これによってバンドルサイズを小さくすることができます

書き換え作業

初期化

まず初期化では、8系までは

import firebase from 'firebase/app'

if (!firebase.apps.length) {
  firebase.initializeApp({ ...config })
}

というようなコードをよく書いていたと思うのですが、9系は

import { initializeApp } from 'firebase/app'
const firebaseApp = initializeApp({ ...config })

という書き方になります<br> また、Firebase AuthとFirestoreは初期化時にappを渡すようになりました

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

const firebaseApp = initializeApp({ ...config })

const firestore = getFirestore(firebaseApp)
const auth = getAuth(firebaseApp)

各機能の書き換え

次に各機能ごとの置き換えです<br> storage, remote config, analyticsあたりはすんなり置き換えられます

例えばstorageによく画像をアップロードすると思うのですが、 v9ではまず、

import { getStorage } from 'firebase/storage'
const storage = getStorage()

とし、

import { ref, uploadBytesResumable, getDownloadURL } from 'firebase/storage'

async uploadImage(path: string, blob: Blob): Promise<string> {
  const imageRef = ref(storage, path)
  const snapShot = await uploadBytesResumable(imageRef, blob)
  return getDownloadURL(snapShot.ref)
}

というようなコードになります<br> 見てわかる通り、必要なメソッドのみをimportする形になりました

Firestoreの書き換え

特にv9になったことでFirestoreの実装に一番違いを感じます<br> ドキュメントのpathの表現の仕方がv8までは

db.collection('users')
  .document('hoge')

という書き方でしたが、v9では

import { doc, getDoc } from 'firebase/firestore'

await getDoc(doc(db, 'users', 'hoge'))

<br> コレクション名とドキュメント名が直感的にわからなくなったので個人的には少し使いづらくなった印象です<br> この書き換え作業でつまずいた点としては、Firestoreでbatchを使うところです<br> batchにはaddがないのでドキュメントを追加する際はsetを使うのですが、setするときにドキュメントIDを自動生成したいときに今までは

docRef = db.collection('users').doc()
batch.set(docRef, dto)

と書いていました<br> これをv9に書き換えると

docRef = doc(collection(db, 'users'))
batch.set(docRef, dto)

と書きます<br> これが公式のドキュメントに書いていなくて理解するのに少し時間がかかりました

さいごに

バンドルサイズが1.14MBから653KBに減りました🎉<br> firebase-adminもv10でmodular形式になったので次はそちらも書き換えていこうと思います