Next.jsとFirebaseで初回ロードでエラーが出る問題の解決

2 min read読了の目安(約2000字

結論

これでエラーを吐かずにSSRのNext.jsでFirebaseの初期化を正常に行えます。

import fb from "firebase/app";
import "firebase/auth";
import 'firebase/firestore';

export const firebase = !fb.apps.length ? fb.initializeApp(config) : fb.app()
export const firestore = firebase.firestore()

https://github.com/vercel/next.js/discussions/11351

解説

ReferenceError: navigator is not defined

Server Errorの対処法

どうやらNext.jsはサーバーサイドでレンダリングするタイミングがあるので、その時におかしな挙動になってしまうらしい。まだSSRに疎いのでたまに遭遇する。

最初は下記の記事を参考にwindowがundefinedの時は初期化しないようにした。

https://qiita.com/GENYA/items/cba59f80d9b678c555db

これを

// appの初期化
if (!firebase.apps.length) {
  firebase.initializeApp(config);
  firebase.analytics();
  firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL);
}

export default firebase
export const firestore = firebase.firestore();

こうする

// appの初期化
if (typeof window !== 'undefined' && !firebase.apps.length) {
  firebase.initializeApp(config);
  firebase.analytics();
  firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL);
}

export default firebase
export const firestore = firebase.firestore();

※ しかし、これではinitializeAppがどうだ〜と言うエラーが出てしまう

FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).

こちらはfirebase appを初期化してないので怒られてます。
さて、そうは言ってもサーバーサイドで初期化処理を行おうとするとエラーになるからな〜と思っていたらVercialのリポジトリでいい記事が有りました。

この記事で解決

https://github.com/vercel/next.js/discussions/11351

今回はimportまで書きました。
firebaseのdefault importをfbと命名するのを採用

そして、appsのlengthが存在すれば初期化したfirebaseAppを返却
なければfirebaseAppをただ返却するだけのコードを書いたら解決しました。

import fb from "firebase/app";
import "firebase/auth";
import 'firebase/firestore';

export const firebase = !fb.apps.length ? fb.initializeApp(config) : fb.app()
export const firestore = firebase.firestore()