この記事はなむゆの個人ブログとのダブルポストです。
ことの発端
最近ぼくの中でまた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キーを別管理にする必要はない、らしい。