firebase functionsからrealtime databaseに接続するのに軽く詰まったのでメモ
2020-08-06
azblob://2022/11/11/eyecatch/2020-08-03-firebase-function-realtimedb-000.jpg

この記事はなむゆの個人ブログとのダブルポストです。

ことの発端

最近ぼくの中でまたfirebase x vue(nuxt)欲が強くなってきていて、(将来のお仕事にもしたいし)再びサイトなんかを作ったりして遊んでいる。
その中で、この間はフロントエンドをfirebase hostingでホストし、APIをfunctionsに作ってそこからrealtime databaseとやりとりするアーキテクチャでサイトを作ろうとした。
その時、functionsからrealtimedatabaseへの接続ってどうやるんだっけ?と軽く混乱して半日ほど潰してしまった。
そこまで高度なテクニックで解決するものじゃない初歩的な話だけど、この先同じ事がまた起こった時に備えてのメモとして、あるいは同じところで詰まった人のため、この記事を残しておきたい。

functionsからrealtime databaseへの接続方法

基本はfirebaseのドキュメントにあるとおりだ。
firebase initでアプリケーションを作ったのだから何か専用の設定をして繋げるんじゃないかと思って色々調べたけれど、そんなこともなかった。
大まかに言うと、javascriptのコードでrealtime databaseに接続するサンプルの通りにすればいい。

firebaseのプロジェクトのページに入って左上の「プロジェクトの概要」の横の歯車から「プロジェクトを設定」を選ぶ。

初期状態ではマイアプリが登録されていないので、「マイアプリを追加」から適当な名前を付けてアプリを追加する。

すると以下のような接続文字列が取得できるのでコピーする。

これを利用してfunctionsのAPIの受け口となるindex.js(あるいは.ts)を以下のようにする。

import * as functions from "firebase-functions";  
import firebase = require("firebase");  
const firebaseConfig = {  
  apiKey: "ここはシークレット",  
  authDomain: "namuyu-functions-test.firebaseapp.com",  
  databaseURL: "https://namuyu-functions-test.firebaseio.com",  
  projectId: "namuyu-functions-test",  
  storageBucket: "namuyu-functions-test.appspot.com",  
  messagingSenderId: "777861796007",  
  appId: "1:777861796007:web:60a7472d9557465d450b82",  
};  
// Initialize Firebase  
firebase.initializeApp(firebaseConfig);  

export const addCurrentTime = functions.https.onRequest((request, response) => {  
  firebase  
    .database()  
    .ref("date/" + new Date())  
    .set({  
      currentTime: new Date().toString(),  
      testData: "sample",  
    });  
});  

この中のfirebaseは初期状態でpackage.jsonに入っていないので、コードを書き換える前後でnpm install firebaseしておくこと!

ここまでやって```npm run serve してurlを叩くと、realtime databaseの方に以下のようにデータが溜まっていくはず。

おわりに

こんな感じに、firebase functionsからrealtime databaseにアクセスしてデータのやり取りを行えるようになる。
が、正直これはjavascriptのコードからであればどこでも同様に行えるので、functionsでなくても同様に動くはずである。
というか、逆にfunctionsなら特別に何かをしなければならないってことでもないというのに気付くのに時間を取ってしまった感じがある。
本来はfirebaseのデータベースにはフロントからクエリを送るとフロントエンドと繋がってデータベースの中身が書き換わるとそれがフロントまで伝搬してリアクティブに表示内容が書き換わるという素敵な機能があったりもするのだけど、そこまでリアルタイムな処理が必要じゃなかったりフロントエンドとバックエンドを分離して最悪バックエンドからfirebaseをはがすとなった時のことも考えると、データベースとのやりとりはfunctions経由で行った方がいいんじゃないかって思うような場合もある。

あと、今回のコードでは接続文字列をコードの中に含めてしまっているが、実際の開発の際にはこれを外部のjsonあたりから受け取るようにして、そのjsonはコード管理とは別に管理することも忘れないように!
2020/8/30追記
どうも実際はAPIキーは隠蔽する必要がないそうな。
フロントエンドにfirebaseを組み込むと配信されるjavascriptにも埋め込まれるので結局APIキーが公開される。
そしたらその公開されたAPIキーで偽の別アプリ作ればfirebase上のデータベースとかアクセスし放題やないかいと思うが、実際にそれで別アプリを作ったところで実際にRead/Writeできるのは設定したルールで決められてる範囲だけだ。
そしてそれらの機能はauthenticationと結びつけられているので、APIキーを入手しても結局別の認証手順を踏まないとリソースの中身をいじれない。
ゆえに実際にはAPIキーを別管理にする必要はない、らしい。