Firebase(version9)をJavaScriptプロジェクトに追加してみる

# はじめに
Firebase JavaScript SDK（バージョン9）を新規のウェブアプリに追加しようとした時に少しハマったので、何かの役に立てばと思い、記事を作ってみました。

基本的には[公式のドキュメント](https://firebase.google.com/docs/web/setup?hl=ja "Firebase を JavaScript プロジェクトに追加する")に解説があります。ただ自分はドキュメントに従って進めてもうまく行かない箇所があり、どうせ観ても分からないと思っていた英語の解説動画を自動翻訳付きで観てようやく理解しました。

ドキュメントでサラッと流されている所が意外と大事だった…というか、単純に自分がES6やモジュールバンドラについて無知だっただけなのですが…

# 前提

ウェブアプリの構成は、利用する言語やフレームワークによって様々な形があると思いますので、この記事ではなるべくシンプルな構成を例にすることで、応用しやすい形になればと思っています。

自分がハマったのはステップ４辺りなのですが、ヘタに途中を省略すると分かりにくくなる可能性もあるかと思いますので、公式ドキュメントの流れに沿って説明しています。

手順の中では、npmがインストールされていることを前提に話が進んでいますので、npmのインストール方法については別途検索していただければと思います。


# ステップ１：　Firebase プロジェクトを作成してアプリを登録する

### Firebaseプロジェクトを作成する
1. Firebaseコンソールで[プロジェクトを追加]をクリックします。
![スクリーンショット 2022-10-03 16.06.36（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417636/2c3739a3-dfe8-41de-1b75-a5a8bf29ccfa.png)

2. プロジェクトに名前をつけて（ここでは「firebase-test」）[続行]をクリックします。

3. Googleアナリティクスは、そのまま[続行]をクリックします。
（※アナリティクスの有無はどちらを選択しても今回は特に影響はありません）

4. アナリティクスアカウントを選択して[プロジェクトを作成]をクリックします。

### アプリを登録する

1. プロジェクトのトップページで[ウェブ]アイコンをクリックします。
![スクリーンショット 2022-10-03 16.08.10（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417636/6d7e3b9e-ad57-40ba-f1c9-e620d7d4bcbc.png)

2. アプリのニックネームを決めて[アプリを登録]をクリックします。

# ステップ２：　SDK をインストールして Firebase を初期化する

続いて、アプリ登録後に表示される以下の画面に従って進めていきます。
![スクリーンショット 2022-10-03 16.08.44（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417636/f0c45e7c-1fa2-9138-d4ed-323bf7373106.png)

1. まずはPCローカルにアプリを格納するフォルダを作成します。ここでは「firebase-test」とします。

2. 作成したフォルダでターミナルを開き、以下のコマンドでnpmからFirebaseをインストールします。ルートフォルダ直下にnode_modulesフォルダ、package.json、package-lock.jsonが作成されるはずです。
```bash
 % npm install firebase
```
3\. 続いて、「firebase-test」フォルダ直下に「src」フォルダを作成し、その中に「index.js」ファイルを作成します。フォルダ構成は以下のような状態になっているかと思います。
```
firebase-test
 ├ node_modules
 ├ src
 │　　　　└　index.js  <=
 ├ package-lock.json
 └ package.json
```

4\. Firebaseのアプリ登録後に表示された以下のコードを 「index.js」ファイルに貼り付けます。（※Analyticsに関する記述は今回は無関係のため、一旦削除しておきます）

```index.js
import { initializeApp } from "firebase/app";

// ここの各パラメータについては、
// Firebaseコンソールに表示された実際の値を貼り付けてください。
const firebaseConfig = {
  apiKey: "...",
  authDomain: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "...",
  measurementId: "..."
};

const app = initializeApp(firebaseConfig);
```

# ステップ３：　アプリで Firebase にアクセスする
今回は正常に動作しているかをFirebase Authenticationを使って簡単に確認したいので、そのための設定をいくつか追加します。

### Firebase Authenticationの開始
1. プロジェクトのコンソール画面から、[Authentication]をクリックします。
![スクリーンショット 2022-10-03 17.50.49（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417636/58f67aca-cce9-3a1a-f10b-3225e52ca84e.png)

2. [始める]をクリックします。

3. ログインプロバイダから[匿名]をクリックします。

4. [有効にする]をオンにし、[保存]をクリックします。

### index.jsの修正
ここではユーザーのログイン状態を監視するために以下の3箇所を追記します。

```index.js
import { initializeApp } from "firebase/app";
import { getAuth, onAuthStateChanged } from "firebase/auth";  // 追記①

const firebaseConfig = {
  apiKey: "...",
  authDomain: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "...",
  measurementId: "..."
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);  // 追記②

// 以下、追記③
onAuthStateChanged(auth, user => {
  if(user) {
    console.log('Logged in!');
  } else {
    console.log('No User.')
  }
});
```

### index.htmlの作成
「src」フォルダ直下に「index.html」ファイルを作成します。
```
firebase-test
 ├ node_modules
 ├ src
 │　　　　├　index.html  <=
 │　　　　└　index.js
 ├ package-lock.json
 └ package.json
```

確認するだけなので、中身は最低限でこんな感じです。
```index.html
<!DOCTYPE html>
<html lang="jp">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Firebase Test</title>
</head>
<body></body>
</html>
```


# ステップ４：　モジュール バンドラ（webpack や Rollup）を使用してサイズを小さくする
自分がハマったのはこの箇所です。この手順の必要性とやり方がよく分かっておらず、index.js1行目のimportが動作せず、ずっと以下のエラーが出ていました。
```
Uncaught SyntaxError: Cannot use import statement outside a module (at index.js:1:1)
```

:::note info
webpackについては、人に説明できるレベルでは理解できていないと思うので、あくまで自分の理解の範囲で簡単に説明すると、もともとJavascriptなどのファイルをバンドルして1つにまとめるためのツールで、バンドルする過程でJavascriptの構文のバージョンを置き換えることなどができます。ここでは、ES6で記述されたFirebaseバージョン9のスクリプトをES5に変換してブラウザで実行できるようにしてくれているものだと思っています。
:::

1. webpackのインストール

ターミナルから以下のコマンドを実行してwebpackをインストールします。
```bash
 % npm i webpack webpack-cli -D
```

2\. 設定ファイルの作成
「firebase-test」フォルダ直下に「webpack.config.js」ファイルと出力用の「dist」フォルダを作成します。
```
firebase-test
 ├ dist  <=
 ├ node_modules
 ├ src
 │　　　　├　index.html
 │　　　　└　index.js
 ├ webpack.config.js  <=
 ├ package-lock.json
 └ package.json
```

「webpack.config.js」の中身には以下のように記述します。
```webpack.config.js
const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',                  // 変換元のエントリーポイントファイルを指定します。
  output: {
    path: path.resolve(__dirname, 'dist'),  // 変換したファイルの出力先フォルダパスと、
    filename: 'bundle.js'                   // 出力するファイル名を指定します。
  },
  devtool: 'eval-source-map',
};
```

3\. webpackの実行
ターミナルから以下のコマンドでバンドルを実行します。
```bash
 % node_modules/.bin/webpack
```
「dist」フォルダ直下に「bundle.js」ファイルができていることを確認します。
```
firebase-test
 ├ dist
 │　　　　└　bundle.js  <=
 ├ node_modules
 ├ src
 │　　　　├　index.html
 │　　　　└　index.js
 ├ webpack.config.js
 ├ package-lock.json
 └ package.json
```

4\. 最後に「index.html」に「bundle.js」を参照するように追記します。
```index.html
<!DOCTYPE html>
<html lang="jp">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Firebase Test</title>
  <script src="../dist/bundle.js"></script>  <!--追記-->
</head>
<body></body>
</html>
```

ブラウザで「index.html」を開いて、「No User.」と表示されていれば問題ないかと思います。
現在ログインしているユーザーを取得した結果、ログインユーザーが存在しないという結果が返ってきています。
![スクリーンショット 2022-10-03 19.53.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417636/d96123bd-afc2-1386-580e-64c6c3f4fd1d.png)

# 補足
公式ドキュメントにも記載がありますが、Angular CLI、Next.js、Vue CLI、Create React AppなどのJavaScriptフレームワークCLIツールを使用している場合は、すでにモジュールバンドラの機能を備えているため、ステップ４の手順は不要とのことです。

# 最後に
個人的には従来のバージョン8やCDNを使った手順の方が断然使いやすい、分かりやすいというのが率直な感想ではありますが、公式ドキュメントから読み取る限り、バージョン9のメリットとしては、ツリーシェイキング（木を揺すって余計なものを振り落とすイメージでしょうか）と呼ばれる、ライブラリ内で使用していない余計なコードを自動で削除してくれるモジュールバンドラの機能と連携することによって、SDKサイズを大幅に削減できる設計になっているという点だと思われます。

大規模な開発でない限り、その恩恵を実感できることはまず無さそうな気はしますが、いずれバージョン8のサポートが終了することを考えると、食わず嫌いせずに頑張って使いこなせるように頑張りたいと思っています。

最後までご覧いただき、ありがとうございました！
至らない点など多々あると思いますが、お気付きの点がありましたら、ご指摘いただけるとありがたいです！