Firebaseでcreate-react-appアプリを公開する基本の手順

サーバー借りてPHPで動いている利用者がほとんどいない既存サービスをFirebase + Reactに移行しようとしています。Firebaseの始め方に関する記事はいろんな方が書いていますが、私もまとめてみました。

# ツールの導入

今回は`create-react-app`を使います。Reactは環境作るだけで疲れるのでこういうのがないと挫けます。`firebase-tools`はデプロイなどFirebaseを操作するために必須です。基本的にグローバルインストールは`package.json`に記載されず依存関係が不明になるので避けるべきだと思いますが、この2つはそういうものではないためグローバルインストールにするのが便利だと思います。

```
$ npm install -g create-react-app
$ npm install -g firebase-tools
```

# `create-react-app`と起動確認

`create-react-app YOUR_APP_NAME`でReactアプリのテンプレートを作ります。今回は`myapp`という名前にします。少し時間がかかりますが待ちましょう。アプリ名は大文字入れると怒られます。

```
$ create-react-app myapp
```

完了後に`npm run start`してみると自動でブラウザが起動し、localhost:3000でアプリが立ち上がります。初心者が自分でReactとビルド環境構築してここまでやろうと思ったらそこそこ大変ですが、`create-react-app`ならたぶん5分もかからずできます。

# Firebaseプロジェクトの準備

[Firebaseコンソール](https://console.firebase.google.com)からプロジェクトを追加し、名前と国を選択します。Googleアカウントが必要です。プロジェクトIDはグローバルで一意であることが必要で、このプロジェクト追加をする段階でしか変更できません。

<img width="535" alt="スクリーンショット 2018-05-02 23.35.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/96536/ba0b9b72-1258-aada-2e5e-cb2dd2d5bcaa.png">

プロジェクトを作成すると、プロジェクトの概要の画面へ飛びます。

# ReactアプリとFirebaseプロジェクトのリンク

最初にFirebaseにログインしておきます。`firebase login`コマンドで認証画面が開くのでFirebaseプロジェクトを作成したGoogleアカウントで認証します。

```
$ firebase login
```

アプリのルートディレクトリに移動してから、`firebase init`コマンドを打ちます。

```
$ firebase init
```

最初は`Which Firebase CLI features do you want to setup for this folder?`と聞かれます。Firebaseの機能のうちどれをこのアプリで使いたいかという質問です。とりあえず全部チェックしておくことにします。

<img width="604" alt="スクリーンショット 2018-05-02 23.56.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/96536/82e1729a-5272-29fc-ec7c-f26dcc795ea4.png">

次に既存のどのFirebaseプロジェクトとアプリを関連付けるかを聞かれます。1つのアプリに対してステージング用と本番用など複数のプロジェクトを関連付けることができるのですが、ここではデフォルトのプロジェクトを選びます。先ほど作成した`myapp`を関連付けます。先ほどのチェックによりますが、その後も次々に質問が来るのでいい感じにかわしていきましょう。

- What file should be used for Database Rules?
    - デフォルト => database.rules.json
- What file should be used for Firestore Rules?
    - デフォルト => firestore.rules
- What file should be used for Firestore indexes?
    - デフォルト => firestore.indexes.json
- What language would you like to use to write Cloud Functions?
    - JavaScript / TypeScript
- Do you want to use ESLint to catch probable bugs and enforce style? (Y/n)
    - ESLintは積極的に入れていきましょう
- Do you want to install dependencies with npm now? (Y/n)
    - どっちでもいいですが、ここで依存関係をインストールしない場合はビルド前にやります
- What do you want to use as your public directory?
    - デフォルト => public
    - `npm run build`すると`build`ディレクトリにビルド結果が入ってくるので`build`を指定します
- Configure as a single-page app (rewrite all urls to /index.html)?
    - Reactを使うのでSPAとして設定します
- What file should be used for Storage Rules?
    - デフォルト => storage.rules

すべての質問に答え終わったら、`firebase.json`を確認しておきます。`firebase init`コマンドでの設定項目はこのファイルで書き換え可能です。

```json
{
  "database": {
    "rules": "database.rules.json"
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint"
    ]
  },
  "hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}

```

# アプリのビルド

`npm run build`でアプリをビルドします。`firebase init`のときに`npm install`しなかったのであればビルド前にやっておきます。ビルドが終わったら`build`ディレクトリにいろいろなファイルができていることを確認しておきましょう。特にソースをいじっていないのであれば、この時点でビルドエラーは出ないはずです。

# Firebaseへのデプロイ

`firebase.json`で`build`ディレクトリをデプロイするという設定をしました。この状態で`firebase deploy`コマンドを打つとデプロイされます。しかし、5大機能をすべてチェックした場合、`firebase deploy`コマンドではhosting以外の機能もデプロイされることになり、ここでエラーが発生します。hosting以外は後々考えるとして、とりあえずは`build`ディレクトリの中身を公開できるようにしましょう。hostingだけをデプロイするときは、`firebase deploy --only hosting`です。

```
$ firebase deploy --only hosting
```

成功すればHosting URLが表示されます。簡単ですね。

# まとめ

サービス移行でちょっとずつ触り始めているところですが、Firebaseさえあればwebアプリは困らないなという風に思い始めているところです。下に挙げた以外にもアクセス解析などの機能も提供しており、しっかり使えればかなり楽に開発が進められるはずです。GoogleアカウントとNode.jsが動く環境さえあれば使えるというのはかなりお手軽ですし、無料枠も十分用意されているのも魅力的です。CircleCIやJestと合わせてテストやデプロイはより簡単にし、爆速で開発を進めていきたいところです。

- Authentication:メール/パスワード、電話番号、Google、Twitter、Facebookなどのログイン方法を簡単に設定できます
- Database:Cloud FireStoreではミリ秒単位でクラウドとリアルタイムに同期するNoSQL型のデータベースが利用できます
- Storage:画像でも音声でもファイルが簡単に保存できます
- Hosting:ReactのようなSPAも配信できます
- Functions:バックエンドコードが実行できます