これからFirebaseでプロジェクトを始めようとする全ての人が知っておくべきこと v8→v9リリース


環境
・MacOS BigSur（11.5.2）
・VScode（1.59.1）
・Node.js   (16.1.1）
・Firebase （9.0.0）←New!
・yarn (1.22.11)
・TypeScript(4.4.2)

## 対象

**・これからFirebaseでプロジェクトを始めようとする人**
:writing_hand:8月25日以前に出された教材やチュートリアル、記事、そして現時点での日本語の公式ドキュメントを参考にしようとしている人は特に！

**・教材や記事、ハンズオン通りにFirebaseでプロジェクトを始めたのに原因不明のエラーぶつかった人**

**・8月25日以前にFirebaseプロジェクト作っている人**


※この記事は2021年9月1日時点の情報です
※情報ソースはFirebaseの公式ドキュメント及び公式に発表されているリリースノートとブログを参考にしています
## はじめに

早速本題に入りますが、つい先日（2021年8月25日）にこれまでベータ版として扱われていた、**Firebase JavaScript SDK (v9.0.0)が正式にリリースされました。**
そしてそれに伴い、**前のバージョンであるv8系のコードとの互換性の問題がある**ことがわかりました。

もう少し正確に説明すると、`npm install firebase`や`yarn add firebase`すると**デフォルトでfirebase v9系のライブラリをダウンロードする**ことになり、これまでのバージョンでのコードの書き方でやってしまうと問題が起きてしまいます。

> "As of today running npm install firebase will download the version 9 library."
[- The Firebase Blog: The new Firebase JS SDK is now GA][1]

今回のリリースでそのためのCompatという互換ライブラリ（後ほど説明します）が用意されていますが、**公式としては将来的にv10かv11あたりでv8の互換ライブラリを完全に削除することが決まっている**ため、これからは基本的にv9を使っていくことをお勧めします。

（2021/10/07追記 ※あれこれ考えるのが面倒でv9以前のハンズオンや教材通りに実装したい方は、のちに紹介するCompatライブラリの使用、もしくはv8系をインストールすることをおすすめします。開拓は強者に任せて、世の中に情報が出回ったタイミングで移行していくのも得策です。）

**ではv9にすることによって何がいいのか？どう実装すればいいのか？**については、**経緯**の次の章に書きます。

（サクッと読みたい方は**経緯**の章を飛ばしてください）

## 経緯

ことの発端は、昨日（9月1日）にFirebaseでプロジェクトを作成していた時に遡ります。
YouTubeのハンズオンをみながらセットアップの実装を進めていました。
その際に以下の様なエラーが発生しました。
![スクリーンショット 2021-09-01 10.41.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711874/eb033387-73f2-8cc1-ec74-602a39739dc8.png)
TypeScriptでやっていたから「お？型エラーが出てるんだな、よしよし型定義だ。」と気楽に考えていましたが、どう工夫してもエラーは消えませんでした。・・あれ？

型定義の問題ではないとしたらなんなのか・・node_modules/firebase/appのファイルの中身と睨めっこしても根本の原因が検討つかず、記事や関連情報を片っ端から調べてもこれに関するエラーを報告している記事が見当たりません。ファッ・・なんてこった！

そこでやっと公式ドキュメントを読みました。

すると、**はじめに**に書いたように、Firebase JavaScript SDK (v9.0.0)が正式にリリースされて前のバージョンであるv8のコードとの互換性の問題があることがわかりました。なんと！

世の中にFirebaseに関する記事や教材は山ほどあるのに、**まだこのことに関して言及している情報が少ない**・・・~~さらに調べるうちに**日本語版の公式ドキュメントが英語版に追いついていない**という事実が確認できました。~~

~~ちなみにv9はベータ版として紹介されたままで、**英語版ではしっかり正式版として紹介されています**🤦‍♀️・・・。~~
（気になる方は例えば[公式ドキュメントのAuthのセットアップのページ][6]を読み進めて日本語から英語に切り替えて比べてみてください。）
追記
→2021年9月22日に確認したところ、日本語版でも正式版として紹介されていました👏

これはいち早く情報を出させばみんなが迷ってしまう・・・！と半ば使命感を感じながら書くに至りました。（🔥）

## 何が変わったの？

実装方法を紹介する前にv9のリリースの**目的**と**何が変わったのか**を簡単に紹介します。

### 目的

[The Firebase Blogの記事][1]によると、今回のv9リリースの主な目的は

**”必要なものだけをインポート”**するアプローチを提供すること。

> This new format provides an "import only what you need" approach.

つまり、このアプローチによって読み込むファイルサイズをできるだけ小さくして、アプリをよりライトにしていこうってことです。（詳しくは読み進めていってもらえるとわかります。）

### 変わったこと

それを達成するために2つの新しいライブラリが導入されました。

・**Modular** - 不要なコードを取り除いてくれるツリーシェイク（tree-shaking）を実行し、ファイルサイズをできるだけ小さく、webアプリの読み込みを素早くできる様にするAPIサーフェス。

・**Compat** -  一度にFirebaseのコードのすべてを変更することなく、バージョン9にアップグレードすることができ、バージョン8 SDKと完全な互換性がありおなじみのAPIサーフェス。 
[公式ドキュメント-Upgrade from version 8 to the modular Web SDK][0]より

Modular （以下、Modular Web SDK）によって、JavaScriptのコードのバンドルサイズを最大80%も削減してくれます。
> The result is a potential significant reduction of Firebase library code in JavaScript bundles, up to 80% in some scenarios.

[The Firebase Blogの記事][1]でサイズ比較していたものがこちらです。
![スクリーンショット 2021-09-01 23.24.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711874/c68bbfab-85e1-3036-5695-ec710b5e5eb7.png)

そして、今回導入されたCompatライブラリでは**残念なことにModular Web SDKのツリーシェイクの恩恵が得られません**。

公式では、**v8系からv9系へ完全に移行するステップとしてのソリューション（一時的な策）**として紹介されています。はじめにも書きましたが、どうしてもv8を使わなければいけない理由がない限り、これからFirebaseでプロジェクトを始める人はもちろん、以前のバージョンを使っている方も、この際v9へ移行してModular Web SDKを使用していくことをお勧めします。

:::note warn
留意点：互換ライブラリは一時的なソリューションであり、将来のメジャーSDKバージョン（バージョン10やバージョン11など）で完全に削除される予定です。最終的な目標は、互換性のあるコードを削除し、バージョン9のモジュラースタイルのコードのみをアプリに保持することです。
:::
[- 公式より][0]

## 実装方法

お待たせしました、ようやく実装編に移ります。

全ては紹介しきれないので、ここでは**Modular Web SDK**と**Compat**でそれぞれ一例を出していきます。
そしてコードベースでv8とv9とでどう変わるのかを把握していきましょう。

### Modular Web SDK

例えばFirebase Authを実装する際に、これまでは

```jsx
// 8.8.1
import firebase from 'firebase/app';
import 'firebase/auth';

const firebaseApp = firebase.initializeApp({ /* config */ });
const auth = firebaseApp.auth();
auth.onAuthStateChanged(user => { console.log(user); });
```

こんな風に書いていましたね。

v9ではこうなります。

```jsx
// 9.0.0
import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged } from 'firebase/auth';

const firebaseApp = initializeApp({ /* config */ });
const auth = getAuth();
onAuthStateChanged(auth, user => { console.log(user); });
```

ポイントは以下の通りです
・最初にinitializeAppをimportしておくこと
・インポート時は`get<service名>`というルールに統一し、`getAuth()`、`getFirestore()`のように関数として使うこと

これは、`firebaseApp.auth()`の様に名前空間とサービスのパターンに基づいて、全てのメソッドが含まれている中から必要なメソッドを使うよりも、 `{ getAuth, onAuthStateChanged }` みたいに最初から個々の関数としてimportしたものを使った方が、バンドルサイズが小さくなるよねっていう考え方に基づくアプローチです。

> While the version 8 APIs are based on a dot-chained namespace and service pattern, version 9's modular approach means that your code will be organized principally around functions. In version 9, the firebase/app package and other packages do not return a comprehensive export that contains all the methods from the package. Instead, the packages export individual functions.
[- 公式より][0]

ちなみにこちらのコードベースだけでもv9のファイルサイズはv8のものより**72%も小さい**そうです。
> The sample above compares the same functionality, has the same amount of lines of code, and a similar API. The version 9 code however is 72% smaller than the version 8 example.
[The Firebase Blog][1]

### Compat

v8系のコードをv9でも使える様にするためには、基本的にimport時のpathにcompatを加えるだけでOKです。

```tsx
import firebase from 'firebase/compat/app'; //compatをpathに加える
import 'firebase/compat/auth';　//compatをpathに加える
import { onAuthStateChanged } from 'firebase/auth';

const firebaseApp = firebase.initializeApp({ /* config */ });
const auth = firebaseApp.auth();
onAuthStateChanged(auth, user => { console.log(user); });
```

こちらの方法は以下のような方におすすめです。

**・できれば情報の多いv8系で実装したい
・v8で構築したけど徐々にv9に移行していきたい**

ちなみに、compatからパッケージをimportしていれば**v8とv9のコードの共存は可能**みたいです。
これだと徐々に移行するのも楽になりますね:smile:
> The same is true for version 8 and version 9 code within a product such as Cloud Firestore; new and old code styles can coexist, as long as you are importing the compat packages:
[- 公式より][0]

## 最後に

これまでFirebaseの設定方法を丁寧に解説してきた方々に敬意を表しながらも、旧バージョンでの情報は今後Firebaseでプロジェクトを始める人にとって障害となりうるので、どうか今回まとめた情報がより多くの人に届くことを願っています。

私自身も今後、FirebaseのAuthenticationやFirestore、Storageなどを使いアプリを構築していくので詳しい実装方法等は別記事にまとめようと思います。

もしも、上記の内容に誤りや過不足等ありましたらコメントで教えていただけると幸いです。

ここまでお読みいただきありがとうございました。

p.s.
ちなみにあたかも知っていたかのように使っていた”SDK”という単語、実は知りませんでしたとさ:yum:
> SDK（Software Development Kit開発キット）とは、少ない労力でアプリケーションを開発できるようにするために、プログラム、API、サンプルコードなどをパッケージにしたものだ。開発者はSDKを使えば、機能を実現する技術の詳しい仕組みを理解していなくても、アプリケーションに新機能を実装できる。さまざまなソフトウェアベンダーが独自のSDKを提供し、自社製品と、サードパーティー製を含む他のアプリケーションを簡単に連携できるよう支援している。
[- TechTarget Japan 「SDK」と「API」の違いとは？ どう使い分ける？][4]

## 参考資料

- 公式[Upgrade from version 8 to the modular Web SDK][0]
- The Firebase Blog [The new Firebase JS SDK is now GA][1]
- 公式リリースノート [Firebase JavaScript SDK Release Notes][2]
- 公式レポジトリ [firebase/firebase-js-sdk][3]
- 公式YouTube動画[Getting started with Firebase for the web – Firebase Fundamentals][5] ←おすすめ

※最後のリンクはクリックしたら動画が再生するので音量注意


[0]:https://firebase.google.com/docs/web/modular-upgrade
[1]:https://firebase.googleblog.com/2021/08/the-new-firebase-js-sdk-now-ga.html
[2]:https://firebase.google.com/support/release-notes/js#9.0.0
[3]:https://github.com/firebase/firebase-js-sdk/discussions
[4]:https://techtarget.itmedia.co.jp/tt/news/1911/07/news06.html
[5]:https://youtu.be/rQvOAnNvcNQ
[6]:https://firebase.google.com/docs/auth/web/start