プロダクションにfirebase v9を入れる記録
WIP
ほんまに入るのか?
いやーすいません なんかトリッキーな使い方してるところがあって、そこで詰まってたら5ヶ月経過してて、Beta抜けてました…
入れ終わりました!
あんまりバンドルサイズは減りませんでした
60KBぐらい?
onSnapshotを使っているためliteは使えない
まとまったらエントリとして会社のブログになるとかあるかもしれない
あんまり面白いことが起きなかった
状態
utilにfirebase.tsを置いて
app
firestore
storage
functions
auth
analytics
messaging
を一元的にimport、initしたものをexportする編成。
手順1
とりあえずyarn add firebase@betaで9.0.0-beta.2を導入。9.1.3を導入。
import 'firebase/hogehoge'となっている部分を一括でimport 'firebase/compat/hogehoge'に置換。
問題点s1
firebase.messaging.isSupported() is not functionが出現
コンパチじゃないんかい!
バグっぽい
しかたなくv9のisSupportedを使おうとするも、ドキュメントが崩壊しているし、なぜかPromise<boolean>
ベータのドキュメント(だけではないが)よく崩壊しがち
とりあえずcompatiだけで通したかったが動作可能でないと意味がないので変更
code:ts
import { isSupported } from 'firebase/messaging'
/*中略*/
export const _messaging =
typeof window !== 'undefined'
? isSupported().then((ok) => (ok ? app.messaging() : null))
: null
使う側でconst messaging = await _messagingとする
https://gyazo.com/7dd8a4053df8c4da8e47244f43576081
壊れた…
なんかそもそもsw登録に失敗してる雰囲気ありますね
なんか手元の調子が悪いのがダメそうだ、一回全てを再起動したいが、今はなんかできない事情がある、どうすれば
https://gyazo.com/406fac36883f82ef64e589b1a633b6f9
Firefoxからだったらうまくいった
firebase-messaging-swのrequire('firebase/package.json')が解決不可に
'./package.json' is not defined by "exports" in ...
const firebaseVersion = require('firebase/app').SDK_VERSIONとして対処したが、
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-app.js'
が404
https://gyazo.com/43512ac64f4f8ba99356dee4bd553f28
はい
firebase-messaging-sw.jsにバンドルしていいんだっけ?
とりあえずここは8.6.1で固定してみる
9.1.3では普通に通る。固定の必要がなくなり外した
手順2
とりあえずcompatで入れることには成功した
次に
messaging
analytics
storage
firestore
auth & app
+ functions
のような順番でcompatへの依存を剥がしていく
大きく変わりすぎることはないと思うが、まだbetaなので現状の仕様に強く依存しすぎないように注意が必要
ここで気が変わりfirebase/compatで調べて出てくる順から直していきます
置き換えパターン集
基本的に型は@firebase/*-typesに移動しているのでそっちから引っ張るようにする
例えばimport type firebase from 'firebase/app'していてfirebase.Userしているものは
import type {User} from '@firebase/auth-types'として持ってくる
ただ一部のTypeはCompatを参照する?ため、firebase/{service}から引っ張ってくる必要がある場合もある
firestore
firestore.collection('users').doc(this.id)
doc(collection(firestore, 'users'), this.id)
ref.collection('users') .orderBy('updatedAt', 'desc').limit(20).get()
await getDocs(query(collection(ref, 'users'), orderBy('updatedAt', 'desc'), limit(20)))
注意点
doc.existsがbooleanから() => booleanに
そのまま使ってるとalways truthyで怒ってくれるが、アーリーリターンなどして!で反転してると怒ってくれない
これもalways falthyで怒ってくれていいと思うんだけど
eslint入れてると前者でも怒ってくれるかも
Authの上書きが禁止に
ライブラリのオブジェクトのプロパティを上書きするのは行儀が良くないので、やらないようにしましょう
それをラップしたオブジェクトなどで対応しましょう
messagingのswはModularする場合importScriptsが使えなくなる
バンドルする必要が出てくる
どうせならTSで書きましょう
このブログはfirebase v9の参考になる情報が多く助かります
Nuxt.jsの場合
esbuildをビルド時のみ使う
code:nuxt.config.ts
hooks: {
build: {
async before(builder) {
const { build } = await import('esbuild')
// esbuildをトップレベルインポートするとnuxt start時にも必要になってprune後に死ぬ
const outfile = join(builder.options.dir.static, 'sw.js')
await build({
bundle: true,
outfile,
})
},
},
},
code:plugin.ts
await this.addTemplate({
src: join(this.options.dir.static, 'sw.js'), // 色々略
code:serviceworker.ts
import { initializeApp } from 'firebase/app'
import { getMessaging, onBackgroundMessage } from 'firebase/messaging/sw'
const setup = (self: ServiceWorkerGlobalScope) => {
...
setup((self as any) as ServiceWorkerGlobalScope) // ちょっと行儀が悪い