個人アプリで使用しているFirebaseをv9に移行した

# はじめに
自分のアプリで使用しているFirebase Javascript SDKをv7からv9へ移行しました。
前のバージョンのコードとの互換性問題により、変更箇所が多かったので備忘録としてまとめます。
内容はFirebaseの初期化処理とFirestoreがメインになります。

# まずは小さく移行 （v8）
v9のFirebaseでは`Compat`というライブラリのおかげで、一度にFirebaseのコードのすべてを変更することなく、互換性を保ったままバージョン9にアップグレードすることができます。

公式も段階的な移行をオススメしているので、まずはv8に移行しました。
https://firebase.google.com/docs/web/modular-upgrade

コードとしてはimport時のpathに`compat`を加えるだけでOK

```js
// v7
import firebase from 'firebase'

// v9(v8)
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
```

これだけでv9のfirebaseをインストールした状態でv7からv8への移行は完了です。

ただし、`Compat`ではv9が提供する`Modular`の恩恵を受けることができません。

**Modular**: 
不要なコードを取り除いてくれる firebase v9のライブラリ。JavaScriptのコードのバンドルサイズを最大80%も削減してくれるらしい！？



# 初期化処理
ここからは完全にv9(`modular方式`)に移行していきます。
まずは初期化処理におけるv7とv9のコードの比較です。

```plugins/firebase.js
// v7
import firebase from 'firebase'

const config = {
  apiKey: process.env.FIREBASE_PROJECT_API_KEY,
  projectId: process.env.FIREBASE_PROJECT_ID
}

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

```plugins/firebase.js
// v9
import { getApps, getApp, initializeApp } from 'firebase/app'

const firebaseConfig = {
  apiKey: process.env.FIREBASE_PROJECT_API_KEY,
  projectId: process.env.FIREBASE_PROJECT_ID
}

const firebaseApp = !getApps().length ? initializeApp(firebaseConfig) : getApp()

export default firebaseApp
```

initializeの書き方が若干変わっています。以前は`firebase.initializeApp()`と書いていたところを`initializeApp`自体をimportしてそのまま実行しています。
必要なものだけimportしているのもv9の特徴ですね。

# データの読み取り

```js
// v9
import { getFirestore, collection, query, orderBy, onSnapshot} from 'firebase/firestore'
import firebaseApp from '../plugins/firebase'

const db = getFirestore(firebaseApp)
const q = query(collection(db, 'info'), orderBy('createdAt', 'desc'))
onSnapshot(q, (snapshot) => {
  snapshot.forEach((doc) => {
    console.log(doc.data()); 
  })
})
```

以前は下記のように、firebaseをまるまるimportした上でFirestoreのインスタンスを取得していました。

```js
// v8
import firebase from 'firebase'
const db = firebase.firestore()
```
v9では特定のモジュールのみをimportすることで、ファイルサイズの削減や高速化に繋がるそうです。
ファイルサイズの削減はv9への移行が落ち着いたら確認してみます。

```js
import { getFirestore, collection, query, orderBy, onSnapshot} from 'firebase/firestore'
```


# データの追加
ユーザーが開発者に要望を送信できる`フィードバック機能`のコードを例に紹介します。（Vue.jsを使用しています）

```js
// v9
import { getFirestore, collection, addDoc, serverTimestamp } from 'firebase/firestore'
import firebaseApp from '../plugins/firebase'

addFeedback() {
  const db = getFirestore(firebaseApp)
  addDoc(collection(db, 'feedback'), {
    feedback: this.feedback,
    created: serverTimestamp()
  })
}
```
やはり`getFirestore()`だけで既存のFirestoreインスタンスにアクセスできるのは良いですね。

あと個人的には`serverTimestamp`がアツいです。
以前の下記のようなコードがv9では短く書けるようになりました。

```js
// v8
created: firebase.firestore.FieldValue.serverTimestamp()
```

# おわりに
まだFirebase v9に少し触れた程度なので、型定義の導入やファイルサイズの削減に取り組んだりしてFirebaseをもっと楽しみたいと思います！

## アプリ宣伝
最後にアプリの宣伝だけさせてください！

https://fgo-damage-calculation.web.app/

スマホアプリ「Fate/Grand Order」で使える計算アプリです。
今回はこのアプリで使用しているFirebaseのバージョンアップ対応を行いました。

FGOユーザーの方でしたら是非一度使ってみて欲しいです！


## 参考記事
v9への移行にあたってお世話になった記事です。
https://zenn.dev/hiro__dev/articles/605161cd5a7875
https://zenn.dev/mktu/articles/3905b13500ffb6#firestore
https://qiita.com/qrusadorz/items/166aa1948dca8bd046a0
https://ascii.jp/elem/000/004/075/4075900/