Firebase Hosting+React+TypeScriptの開発環境を作成しよう

# 準備

Firebaseの管理コンソールに従って、firebase deployができる状態になるまでまずはもっていきましょう。
Hostingで公開するのにローカルで編集するローカルディスク上のディレクトリーが仮にpublicだとした場合、publicをいったん消しましょう。

```
$ rm -rf public
```

# テンプレートアプリを作成

```
$ npx create-react-app public --typescript
```

# firebase.jsonを編集

public/buildディレクトリーをFirebaseに公開するので、public/buildにします。

```
{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "hosting": {
    "public": "public/build",
    "ignore": [
      "firebase.json",
      "**/package-lock.json",
      "**/public/**",
      "**/package.json",
      "**/README.md",
      "**/yarn.lock",
      "**/src/**",
      "**/.*",
      "**/node_modules/**"
    ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}
```

## (余談)複数のサイトを運用するときは、"hosting"エントリーの値を配列にする

```
{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "hosting": [{
    "site": "foo",
    "public": "foo/build",
    "ignore": [
      〜
    ]
  },
  {
    "site": "bar",
    "public": "bar/build",
    "ignore": [
      〜
    ]
  }],
  "storage": {
    "rules": "storage.rules"
  }
}
```

# まずは動作確認

次のコマンドを実行しましょう。

```
$ cd public
$ npm start
```

自動的にWebブラウザーが開いて以下の画面が表示されたら成功です。
<img width="508" alt="スクリーンショット 2019-07-27 1.27.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64294/133b15cf-f264-dd43-205b-0c4ccc03b52b.png">

ただし、これだけではReactとTypeScriptの開発環境ができただけです。
まだFirebaseの機能は使用できません。

# Firebaseパッケージをインストール

Webに公開するWebアプリなので、Firebaseの公式ドキュメントの通りにscriptタグで読み込ませたいところですが、せっかくnpmでパッケージをインストールできるので、npmを使ってインストールしましょう。
こうした方が管理しやすいですしね。

```
$ npm i --save firebase firebase-tools
```

# FirestoreとCloud Storage for Firebaseのセキュリティルールを修正

APIキーを公開するので、FirestoreとClouse Storage for Firebaseのセキュリティールールが甘いと費用がかさんだり、無料枠を使い切ってアカウントがロックされるといったことが起こりかねません。
ログインしてなくては使用できない設定に変更しましょう。

後で匿名ログインを有効にするのでログイン状態になると考えていてください。

```firestore.rules
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth.uid != null;
    }
  }
}
```

```storage.rules
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth.uid != null;
    }
  }
}
```

# Firebaseへの接続設定を書き込む

不要なimportや、機能は適宜取り除いてください。

```public/src/firebase.tsx
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import "firebase/functions";
import "firebase/messaging";
import "firebase/storage";
import "firebase/performance";

const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  databaseURL: "https://YOUR_DATABASE_URL",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID"
};

firebase.initializeApp(firebaseConfig);

firebase.performance();
firebase.auth().signInAnonymously();

export default firebase;
```

firebaseConfigは、Firebaseの管理コンソールから取得します。

![スクリーンショット 2019-07-27 1.55.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64294/ebeac7b2-2425-5890-e635-7b037de3060b.png)

赤枠の部分をコピペしましょう。

# firebase.tsxをインポートする

App.tsxなど、Firebaseに接続するソースに以下のimport分を追加すると使えるようになります。

```
import firebase from './firebase';
```

例えば、FirestoreのSDKを使いたければつぎのようにします。

```
const db = firebase.firestore();
```

# Firebaseで匿名ユーザーを有効にする

<img width="551" alt="スクリーンショット 2019-07-27 2.06.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64294/a572d74a-31ff-30d0-b331-43897b46f018.png">

# 開発業務を行う

firebase serveコマンドで確認したいところかもしれませんが、それだとTypeScriptがコンパイルされなかったり、Reactが動作しないので、npm startコマンドを実行してください。

```
$ npm start
```

ブラウザーが開いて、Reactの画面を表示します。JavaScriptのコンソールにエラーが表示されていなければ匿名ログインができていると判断してください。

プログラムソースを編集したらブラウザには即座に変更が反映されますので開発がしやすいですね。

# Firebaseにデプロイする

Firebaseいデプロイするには、npmでビルドしてからデプロイします。

```
$ cd public
$ npm run build
$ cd ..
$ firebase deploy
```

firebase deployの終わりの方にURLが表示されるので、そのURLにアクセスしてデプロイを確認してみてください。

# 終わりに

かなり端折りましたが、基本的にはこれで開発を進められると思います。