DartでFirebase Functionsを書く手法

ntaoo
7 min readMay 5, 2020

--

ドラフト版を公開しています。調査、検証を進めるたびに、この記事を更新していきます。

2020/05/05: 初稿

2020/06/27: 追記。Dart 2.8.1の破壊的変更に対応

2020/07/08: 実験的に、firebase-functions-interopとfirebase-admin-interopを採用したプロジェクトをオープンソースにしました。

なぜFirebase FunctionsをDartで書くのか?

FlutterとModelのコードを共有できます。

最低でも、Firestore pathに関するコードをシェアできます。

たとえば、Chat appならば、Message Body の Parser をそのまま再利用できるので、異なる言語で再実装したときにありがちな parse の解釈結果の差異の発生を防止できます。

クラサバを同一言語で書けると、思考のコンテキストスイッチを防止して、Flutterで得たDartのノウハウをFunctionsでも活かせます。

少人数開発では特にこのベネフィットが大きいです。

利用するPackages

firebase-functions-interop

(2020/06/27: 追記) Dart 2.8.1の破壊的変更に対応するため、以下のcommitを利用します。

firebase-admin-interop

公式のPackageではありません。複雑なことはまだ試していませんが、今のところ不具合に遭遇することはなく、快適です。

注意点

現状(2020/05/05)はバージョン解決に失敗しますので、回避策としfirebase_functions_interopについては、Skquark氏のフォーク版を指定する必要があります。

(2020/06/27: 追記) さらに、Dart 2.8.1の破壊的変更に対応するため、以下のcommitを利用しています。

dependencies:
firebase_functions_interop:
git:
url: git://github.com/ntaoo/firebase-functions-interop
branch: update_deps
firebase_admin_interop: ^2.1.0

また、現在、Firebase Adminの最新のバージョンに追随しているわけではないので、その差分を確認しておくことが大事です。Firestoreならば、https://github.com/googleapis/nodejs-firestore/blob/master/CHANGELOG.md を見て、Interop Codeが追いついていないであろう箇所を把握します。

不具合を見つけたらコントリビューションチャンス、の精神でやっていきます。業務で採用するかはその事情を勘案した上で判断。

( Pure Dartで書いたコードをJavaScriptにコンパイルしてそれをライブラリとしてJavaScript / TypeScriptで書いたFunctionsから利用することもできるでしょうが、非公式packageであるリスクを受け入れるならば、こちらの手法のほうが生産性が高いでしょう。)

プロジェクトのセットアップ

サンプルプロジェクト

ビルド

サンプルプロジェクトのREADMEを参照してください。

デプロイ

サンプルプロジェクトのREADMEを参照してください。

Firebase Emulatorを使う

TBE

サンプルコード

READMEやexample/では十分な例が載っていないので、テストコードを見て使い方を把握します。

Firestore

Document data の get / set

テストコードのこの箇所で示されています。

Timestampを扱う

このように書きます。

final now = Timestamp.fromDateTime(DateTime.now());
DocumentData.fromMap({})..setTimestamp('createdAt', now);

なお、firebase-admin-interop のREADMEに記載されている、以下のmigration用の指定は、package.jsonで @google-cloud/firestore v3.0.0 以降を指定した場合は、必要ないようです。

// Not necessary.
firestore.settings(FirestoreSettings(timestampsInSnapshots: true));

これは、v3.0.0において、

remove deprecated timestampInSnapshots

となったためです。

以下、TBE。

--

--