落とし穴に立て札を立てるが如く

ハマりどころの解決が少しでも早くなることを願って書いていきます

firebase functionsからrealtime databaseに接続するのに軽く詰まったのでメモ

f:id:nam_yu_sql:20200802203941j:plain この記事は後ほどcloud.config tech blogに転載する予定です。

ことの発端

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

functionsからrealtime databaseへの接続方法

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

firebaseのプロジェクトのページに入って左上の「プロジェクトの概要」の横の歯車から「プロジェクトを設定」を選ぶ。
f:id:nam_yu_sql:20200802204009p:plain
初期状態ではマイアプリが登録されていないので、「マイアプリを追加」から適当な名前を付けてアプリを追加する。
f:id:nam_yu_sql:20200802204027p:plain
すると以下のような接続文字列が取得できるのでコピーする。
f:id:nam_yu_sql:20200802204040p:plain
これを利用して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の方に以下のようにデータが溜まっていくはず。
f:id:nam_yu_sql:20200802204216p:plain

おわりに

こんな感じに、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キーを別管理にする必要はない、らしい。