Help us understand the problem. What is going on with this article?

React x Firebase を用いた Web アプリケーション開発時のハマりどころと解決策

概要

これから React x Firebase の構成で Web アプリケーションを開発する方が同じところでハマらないようにハマりどころと解決策をまとめました。

この資料は Firebase Meetup #15 Cloud Functions Day の LT 資料です。

スライドは以下です。
React x Firebase を用いた Web アプリケーション開発時のハマりどころと解決策 - Speaker Deck

1. Hosting と同じドメインで Cloud Functions の関数を呼び出す

Cloud Functions のデフォルトで生成される URL は以下ですが、

https://[region]-[project id].cloudfunctions.net/[function name]

以下の URL で呼び出したいことがあります。

  • https://[project id].web.app/[function name]
  • https://[project id].firebaseapp.com/[function name]
  • https://[独自ドメイン]/[function name]

Hosting の設定ファイルである firebase.json の rewrites の設定をすれば OK です。以下の設定で /notifications にアクセスされた時に Cloud Functions の notifications 関数を実行し、その他のパスにアクセスされた場合は index.html が参照されます。

firebase.json
  "hosting": {
    "rewrites": [
      {
        "source": "/notifications",
        "function": "notifications"
      },
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]

Functions は以下のように、通常通り実装すれば良いです。

functions/index.js
exports.notifications = functions
  .https
  .onRequest((req, res) => {
    // ...
  };

2. ローカル環境の React から Emulator の Functions を呼び出す

やりたかったことは以下です。

  • Functions をいちいちデプロイして検証したくない
  • React のホットリロードはそのまま使いたい

そのため、 React は yarn start して Functions は emulator を使って接続します。 Functions をローカルで動作させるために Emulator Suite を使います。

Command
$ firebase emulators:start --only functions
src/index.js
const app = firebase.initializeApp(config)

if (process.env.NODE_ENV === 'development') {
  app.functions().useFunctionsEmulator('http://localhost:5001')
}

3. React と Functions で Firestore の参照先を合わせる

2 の設定を行った場合、 Firestore を利用していると以下のような状態になります。

  • React: Cloud の Firestore を参照
  • Functions: Emulator の Firestore 参照

そのため、Cloud か Emulator か参照先を統一する必要があります。

3-1. Cloud の Firestore を参照する

以下のような構成です。

  • React: yarn start
  • Functions: Emulator
  • Firestore: Cloud

この場合のメリデメは以下のようになります。

  • メリット: 開発時に Firebase console からデータを確認できる
  • デメリット: Cloud のデータが更新されるため、複数人開発には不向き。リリース後は Firebase を複数プロジェクト構成 にするなどの工夫が必要

設定は以下のように行います。Functions のディレクトリで @google-cloud/firestore パッケージをインストールして、 functions/index.js からそのパッケージを利用します。 引数には Firebase の project id を指定します。

Command
$ npm install --save @google-cloud/firestore
functions/index.js
const Firestore = require('@google-cloud/firestore')
const admin = require('firebase-admin')

const db = (() => {
  if (process.env.FUNCTIONS_EMULATOR) {
    return new Firestore({ projectId: 'your project id' })
  } else {
    return admin.firestore()
  }
})()

公式ドキュメントの 認証の開始 ページからサービスアカウントキーを作成してローカルに配置し、 .bashrc や .zshrc などに追記しておきます。

Command
$ export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"

3-2. ローカルの Firestore を参照する

以下のような構成です。

  • React: yarn start
  • Functions: Emulator
  • Firestore: Emulator

この場合のメリデメは以下のようになります。

  • メリット: ローカル環境に閉じてデータを変更できるので複数人開発やリリース後の運用にも向いている
  • デメリット: データの確認が難しい

デメリットとしてデータ確認が難しいとしましたが、これは Firestore CLI などがない(?)ためで、もし良いアクセス方法ご存じの方いたらコメントください。

設定は以下のように行います。公式ドキュメント でもこの方法が紹介されています。

Command
$ firebase emulators:start --only functions,firestore
src/index.js
const app = firebase.initializeApp(config)

if (process.env.NODE_ENV === 'development') {
  app.functions().useFunctionsEmulator('http://localhost:5001')
  db.settings({
    host: "localhost:8081",
    ssl: false
  });
}

4. Hosting から asia-northeast1 region の Functions を呼び出せない

以下のように region 指定をすると Hosting から呼び出せなくなる

functions/index.js
exports.getEvents = functions
  .region(asia-northeast1)
  .https()
  .onCall((data) => {
    // ...
  });

スクリーンショット 2019-12-02 14.49.50.png

公式ドキュメント を見ると

Firebase Hosting は、us-central1 でのみ Cloud Functions をサポートします。

との記述が。。というわけで、Hosting とつなぐ Function は、現状 region 指定しないで運用するしかなさそうです。

以上!

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away