1. はじめに
目標
この Codelab では、Firebase Extensions を利用して、オンライン マーケットプレイス アプリに機能を追加します。この Codelab では、拡張機能を使用してアプリの開発や管理のタスクに費やす時間を短縮する方法について説明します。
作成するアプリの概要
この Codelab では、オンライン マーケットプレイス ウェブアプリに次の機能を追加します。
- 画像の読み込みを高速化してユーザー維持率を高める
- データベースのエントリを制限することで、パフォーマンスを向上させ、費用を削減できます
- 古いユーザーデータの自動削除を実装してユーザーデータの保護を強化する
ラボの内容
- 一般的なユースケースの拡張機能を見つける方法
- プロジェクトに拡張機能をインストールして構成する方法
- プロジェクトで拡張機能を維持(モニタリング、更新、アンインストール)する方法
この Codelab では Firebase Extensions を中心に説明します。この Codelab で紹介している他の Firebase プロダクトについて詳しくは、Firebase のドキュメントと他の Codelab をご覧ください。
必要なもの
- 最新のウェブブラウザがインストールされているパソコン(Chrome を推奨)
- Google アカウント
2. Firebase プロジェクトを作成して設定する
Firebase プロジェクトを作成する
- Firebase コンソールで [プロジェクトを追加] をクリックし、Firebase プロジェクトに「FriendlyMarket」という名前を付けます。
- プロジェクト作成オプションをクリックします。Firebase の利用規約に同意します。このアプリではアナリティクスを使用しないため、Google アナリティクスの設定はスキップします。
- プロジェクトがプロビジョニングされるまで待ってから、[続行] をクリックします。
構築するアプリケーションでは、ウェブアプリで利用可能な Firebase プロダクトをいくつか使用します。
- ユーザーを簡単に識別できる Firebase Authentication
- Firebase Realtime Database: 構造化データをクラウドに保存し、データが更新されるとすぐに通知を受け取ります。
- Cloud Storage for Firebase: クラウドに画像を保存
次に、Firebase コンソールを使用して、これらの Firebase プロダクトを有効にして構成します。
メールログインを有効にする
認証はこの Codelab の焦点ではありませんが、アプリで使用するなんらかの認証方法を実装して、それを使用するユーザーを一意に識別することが重要です。メールによるログインを使用します。
- Firebase コンソールで、左側のパネルにある [開発] をクリックします。
- [Authentication] をクリックし、[Sign-in method] タブをクリックします(またはこちらをクリックして、[Sign-in method] タブに直接移動します)。
- [ログイン プロバイダ] リストで [メール/パスワード] をクリックし、[有効にする] スイッチをオンにして [保存] をクリックします。
Realtime Database を有効にする
このアプリは、Firebase Realtime Database を使用して販売する商品アイテムを保存します。
- Firebase コンソールの左側のパネルにある [開発] セクションで、[データベース] をクリックします。
- [Cloud Firestore] ペインまでページを下にスクロールし、[Realtime Database] ペインで [データベースを作成] をクリックします。
- [ロックモードで開始] を選択し、[有効にする] をクリックします。
セキュリティ ルールを設定する
次に、このアプリに必要なセキュリティ ルールを設定します。これらは、アプリの保護に役立つ基本的なサンプルルールです。これらのルールでは、販売対象のアイテムは誰でも閲覧できますが、その他の読み取りと書き込みを行うことはログイン ユーザーのみが許可します。これらのルールの詳細を気にする必要はありません。これらのルールをコピーして貼り付けるだけで、アプリを稼働させることができます。
- Realtime Database ダッシュボードの上部にある [ルール] タブをクリックします。
- 次のルールセットをコピーして、[ルール] タブの [ルール] フィールドに貼り付けます。
{
"rules": {
".read": false,
".write": false,
"drafts": {
".indexOn": "seller",
".read": "auth.uid !== null",
".write": "auth.uid !== null"
},
"sellers": {
".read": "auth.uid !== null",
".write": "auth.uid !== null"
},
"forsale": {
".read": true,
".write": "auth.uid !== null"
}
}
}
- [Publish] をクリックします。
Cloud Storage を有効にする
このアプリは、Cloud Storage for Firebase を使用して、販売する商品の画像を保存します。
- Firebase コンソールの左側のパネルにある [開発] セクションで、[Storage] をクリックします。
- [Get started] をクリックします。
- デフォルトのストレージ バケットを作成する際のデフォルトを受け入れます([次へ] をクリックし、場所はデフォルトのままにして [完了] をクリックします)。
次に、このアプリに必要なセキュリティ ルールを設定します。このルールでは、認証されたユーザーに新しい画像の投稿のみを許可し、リストにあるアイテムの画像を誰でも閲覧できるようにします。
- [Storage] ダッシュボードの上部にある [ルール] タブをクリックします。
- 次のルールセットをコピーして、[ルール] タブの [ルール] フィールドに貼り付けます。
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
match /friendlymarket/{ImageId} {
allow read;
allow write: if request.auth != null;
}
}
}
- [Publish] をクリックします。
3. サンプルアプリを実行する
StackBlitz プロジェクトをフォークする
この Codelab では、複数の Firebase ワークフローが統合されたオンライン エディタである StackBlitz を使用して、アプリをビルドしてデプロイします。Stackblitz では、ソフトウェアのインストールや特別な StackBlitz アカウントは必要ありません。
StackBlitz を使用すると、プロジェクトを他のユーザーと共有できます。あなたの StackBlitz プロジェクトの URL を知っている他のユーザーは、あなたのコードを見てプロジェクトをフォークできますが、StackBlitz プロジェクトを編集することはできません。
- 開始用コードの URL https://stackblitz.com/edit/friendlymarket-codelab に移動します。
- [StackBlitz] ページの上部にある [Fork] をクリックします。
これで、開始コードのコピーが独自の StackBlitz プロジェクトとして作成されました。ログインしていないため、「アカウント」の名前は「@anonymous
」ですが、問題ありません。プロジェクトには一意の名前と URL が設定されています。ファイルと変更はすべて、この StackBlitz プロジェクトに保存されます。
プロジェクトに Firebase ウェブアプリを追加する
- StackBlitz で
src/firebase-config.js
ファイルを表示します。このファイルに Firebase 構成オブジェクトを追加します。 - Firebase コンソールに戻り、左上の [プロジェクトの概要] をクリックして、プロジェクトの概要ページに移動します。
- プロジェクトの概要ページの中央にあるウェブアイコン をクリックして、新しい Firebase ウェブアプリを作成します。
- FriendlyMarket Codelab というニックネームでアプリを登録します。
- この Codelab では、[このアプリの Firebase Hosting も設定します] の横のボックスをオンにしないでください。代わりに StackBlitz のプレビュー ペインを使用します。
- [アプリを登録] をクリックします。
- アプリの Firebase 構成オブジェクトをクリップボードにコピーします。
<script>
タグはコピーしないでください。注: 後で構成を確認する必要が生じた場合は、こちらの手順に沿って操作してください。
- [コンソールに進む] をクリックします。
プロジェクトの構成をアプリに追加します。
- StackBlitz に戻り、
src/firebase-config.js
ファイルに移動します。 - 構成スニペットをファイルに貼り付けます。設定すると、次のようになります(ただし、構成オブジェクトに自分のプロジェクトの値が指定されている)。
このアプリの出発点
StackBlitz 画面の右側にあるインタラクティブ プレビューを見てみましょう。
この Codelab では、基本的な Marketplace アプリのコードから始めます。すべてのユーザーが、販売アイテムのリストを表示し、リンクをクリックしてアイテムの詳細ページを表示できます。ユーザーがログインすると販売者の連絡先情報が表示され、価格交渉や商品の購入が可能になります。
アプリを試してみましょう。
- ホーム画面の上部にあるボタンを使用してログインします。偽のメールアドレス、名前、パスワードを使用できます。
- 右下隅にある [Sell 何か] ボタンをクリックして、リスティングを作成します。
- [Title] に「
Xylophone
」と入力します。 - [Asking Price] に「
50
」と入力します。 - [Item Description] に「
This high quality xylophone can be used to play music.
」と入力します。 - このシロフォンの画像をパソコンにダウンロードし、[商品画像] ボタンを使ってアップロードします。
- すべてのフィールドに入力し、画像をアップロードしたら、[投稿] をクリックします。
- 新しい掲載情報を探します。商品アイテムをクリックして詳細画面を開き、[販売者の連絡先情報] パネルを展開します。
- Firebase コンソールに戻ります。[Database] ダッシュボードの
forsale
ノードの下に投稿したアイテムのエントリが表示されます。Storage ダッシュボードでは、friendlymarket
パスにアップロードした画像も表示されます。
4. 拡張機能を検索してインストールする
問題点
アプリのユーザー調査を行った結果、ほとんどのユーザーがパソコンからではなくスマートフォンからサイトにアクセスしていることがわかりました。一方で、モバイル ユーザーは数秒後にサイトを離れる(「離脱」)傾向があることもデータによって示されています。
不思議に、あなたはモバイル接続速度で自分のサイトをテストしました。(方法についてはこちらをご覧ください)。画像の読み込みに非常に時間がかかり、ブラウザのキャッシュに保存されていないことがわかりました。その分、ページビューのたびに読み込み時間が長くなります。
解決方法
画像を最適化する方法を読み終え、画像の読み込みパフォーマンスを改善するために、次の 2 つのステップを実施することにしました。
- 画像を圧縮する。スマートフォンでも、このアプリに必要な解像度よりもはるかに高い解像度で画像を撮影できます。ファイルサイズを小さくすると、アプリの解像度が大きく低下することなく、読み込み時間が短縮されます。
- キャッシュ。デフォルトでは、Cloud Storage オブジェクトには画像をキャッシュに保存しないようブラウザに指示するヘッダーがあります。つまり、ユーザーのブラウザは同じ画像を何度も再ダウンロードします。幸いなことに、これらのヘッダーを変更してキャッシュを許可できます。クライアントサイドの Cloud Storage SDK と Firebase Admin SDK の両方で、これらのヘッダーを設定できます。
画像を圧縮するには、アップロードの品質を制限するか、画像のサイズを変更するサーバーサイド プロセスを用意する必要があります。トレードオフについて検討します。
- クライアントサイド。クライアントサイドのプロセスでは、アップロードする画像のファイルサイズを制限するだけです。つまり、新しいサーバー ロジックを記述または維持する必要はありません。ただし、販売者は独自の画像のサイズを変更する方法を把握しなければならないことも意味します。これは、新しいリスティングを作成するうえで直観的でなく、手間がかかります。
- サーバーサイド。Cloud Functions for Firebase を使用する場合は、アップロード時に画像のサイズを自動的に変更する関数をトリガーできます。つまり、販売者は好きなサイズの画像をアップロードでき(追加作業は不要)、バックエンド関数で画像をシームレスにサイズ変更できます。この関数のサンプルも用意されています。
サーバーサイドが向いているように思えますが、この方法では、サンプルのクローンを作成し、設定手順に沿って Firebase CLI を使用して関数をデプロイします。画像のサイズ変更は、このような一般的なユースケースのように聞こえます。もっと簡単な解決策はありませんか?
より簡単なソリューション
ご健闘をお祈りします。それよりも簡単な解決策は Firebase Extensions です。Firebase ウェブサイトで利用可能な拡張機能のカタログを確認してみましょう。
「画像のサイズ変更」という拡張機能があります。有望なようです。
この拡張機能をアプリで使用してみましょう。
拡張機能をインストールする
- [詳細を表示] をクリックすると、この拡張機能の詳細が表示されます。[設定できる内容] では、この拡張機能を使用してサイズ変更の基準とするサイズを設定できます。また、キャッシュ ヘッダーを設定することもできます。正解です。
- 拡張機能の詳細ページにある [コンソールでインストール] ボタンをクリックします。Firebase コンソールのページが開き、すべてのプロジェクトが一覧表示されます。
- この Codelab 用に作成した FriendlyMarket プロジェクトを選択します。
- [拡張機能を設定する] ステップが表示されるまで、画面上の手順に沿って操作します。この手順には、拡張機能の基本的な概要と、拡張機能によって作成されるリソース、必要なロールへのアクセスが表示されます。
- [**
Cache-Control
**サイズ変更された画像のヘッダー] に次のように入力します。
public, max-age=31536000
- 他のパラメータはデフォルト値のままにします。
- [拡張機能をインストール] をクリックします。
インストールの完了を待っている間に...
Firebase コマンドライン インターフェースを使用したインストール
コマンドライン ツールに慣れている場合は、Firebase CLI を使用して拡張機能をインストールして管理することもできます。そのためには、最新バージョンの CLI で利用可能な firebase ext
コマンドを使用します。詳しくは、こちらをご覧ください。
(省略可) Cache-Control ヘッダーの詳細
Cache-Control ヘッダーの値 public, max-age=31536000
は、画像が最大 1 年間キャッシュに保存されることを意味します。Cache-Control ヘッダーの詳細については、こちらのドキュメントをご覧ください。
クライアント コードを更新する
インストールした拡張機能により、サイズ変更された画像が元の画像と同じバケットに書き込まれます。サイズ変更された画像には、設定されたサイズがファイル名に付加されます。そのため、元のファイルパスが friendlymarket/user1234-car.png
の場合、サイズ変更された画像のファイルパスは friendlymarket/user1234-car_200x200.png
のようになります。
フルサイズの画像ではなく、サイズ変更された画像を取得するようにアプリを更新します。
- StackBlitz で
src/firebase-refs.js
ファイルを開きます。 - 既存の
getImageRef
関数を次のコードに置き換えて、サイズ変更された画像の参照を作成します。
export function getImageRef(storage, imagePath) {
const xDimension = 200;
const yDimension = 200;
// find the '.' in 'file.jpg', 'file.png', etc
const fileExtensionIndex = imagePath.lastIndexOf('.');
const pathNameWithoutExtension = imagePath.substring(0, fileExtensionIndex);
const dimensions = `${xDimension}x${yDimension}`;
const fileExtension = imagePath.substring(fileExtensionIndex);
return {
resized: storage().ref(
`${pathNameWithoutExtension}_${dimensions}${fileExtension}`
),
original: storage().ref(imagePath)
};
}
テストする
この拡張機能は新しい画像のアップロードを監視するため、既存の画像のサイズを変更することはありません。
新しい投稿を作成して、拡張機能の動作を確認します。
- アプリのトップバーにある [Friendly Market] をクリックしてホーム画面に移動します。
- アプリの右下にある [Sell 何か] ボタンをクリックして、掲載情報を作成します。
- [タイトル] に「
Coffee
」と入力します。 - [Asking Price] に「
1
」と入力します。 - [Item Description] に「
Selling one cafe latte. It has foam art in the shape of a bear
」と入力します。 - このコーヒーの画像をパソコンにダウンロードし、[商品画像] ボタンを使ってアップロードします。
- すべてのフィールドに入力し、画像をアップロードしたら、[投稿] をクリックします。シロフォンの下にコーヒー リストが表示されます。
- Firebase コンソールの [Functions] ダッシュボードで、[ログ] タブをクリックします。関数が実行されたことを示すログが表示されます。
- [Storage] ダッシュボードに移動して、
friendlymarket
パスにある元のコーヒー画像とサイズ変更されたバージョンの両方を確認します。 - StackBlitz のプレビュー ペインで、アプリのホーム画面を数回再読み込みします。コーヒーの画像は、シロフォンの画像よりかなり速く読み込まれることがわかります。
この画像はサイズが小さいため、最初のページの読み込み時は速く読み込まれ、それ以降のページ更新時はネットワーク リクエストをトリガーせずにブラウザのキャッシュから読み込まれます。
5. 拡張機能を再構成する
問題点
販売者の掲載情報の下書き版が自動保存されます。ユーザーはこの機能を高く評価していますが、統計情報には少し懸念があります。レポートによると、実際に投稿された下書きは 10% 程度で、残りの 90% はデータベースの容量を占有しているだけです。
解決方法
簡単な計算を行うと、一度に保存する必要がある下書きは 5 つほどであることがわかりました。
Firebase Extensions のカタログを覚えていますか?この状況に対応したソリューションがすでに構築されているのかもしれません。Limit Child Nodes 拡張機能をインストールして、保存された下書きの数を自動的に 5 つ以下に保ちましょう。この拡張機能では、新しい下書きが追加されるたびに最も古い下書きが削除されます。
- 拡張機能の詳細ページで [インストール] ボタンをクリックします。
- Marketplace ウェブアプリに使用している Firebase プロジェクトを選択します。
- [拡張機能を設定する] ステップが表示されるまで、画面上の手順に沿って操作します。
- [Realtime Database のパス] に「
drafts
」と入力します。これは、下書きが保存されるデータベース内のパスです。 - [保持するノードの最大数] に「
5
」と入力します。つまり、アイテムの掲載情報ごとに 5 つの下書きが保存され、別の下書きが追加された場合、最も古い下書きが自動的に削除されます。 - [拡張機能をインストール] をクリックします。
インストールの完了を待っている間に...
拡張機能のモニタリング
拡張機能をインストールすると、プロセスによっていくつかの関数が作成されます。これらの関数の実行頻度や、ログやエラー率を確認できます。拡張機能をモニタリングする方法については、インストールした拡張機能を管理するをご覧ください。ドキュメントの指示に従って、前のステップで Resize Images 拡張機能によって作成された関数を表示します。
拡張機能のアンインストール
プロジェクトから拡張機能を削除するために、拡張機能によって作成された関数を個別に削除したいと思うかもしれませんが、1 つの拡張機能で複数の関数が作成される可能性があるため、予期しない動作が発生する可能性があります。拡張機能をアンインストールする方法については、ドキュメントをご覧ください。
アンインストールすると、すべてのリソース(拡張機能の関数など)と、拡張機能のそのインスタンス用に作成されたサービス アカウントが削除されます。ただし、拡張機能によって作成されたアーティファクト(サイズ変更された画像など)は、拡張機能をアンインストールした後もプロジェクトに残ります。
1 つのプロジェクトに拡張機能の複数のコピーをインストールする
プロジェクトにインストールする拡張機能のインスタンスは 1 つに制限されません。別のパスのエントリを制限する場合は、この拡張機能の別のインスタンスをインストールします。ただし、この Codelab の目的上、拡張機能のインストールは 1 回のみとします。
実例を見る
- シロフォンまたはラテの投稿に使用したアカウントでログインしていることをご確認ください
- 下書きを生成します。
- アプリの右下にある [Sell 個] ボタンをクリックします。
- [タイトル] を編集して「下書き 1」と記入します。
- [下書き] セクションまで下にスクロールし、下書きの数を確認します。少なくとも 2 つ必要です。
- 上部のアプリバーにある [FRIENDLY MARKET] ボタンをクリックします。保存した下書きは、投稿しなくても使用できます。
- 「下書き 2」、「下書き 3」などについて「下書き 6」まで繰り返します。
- 「下書き 6」を作成すると、[下書き] セクションに [下書き 1] が表示されなくなります。
- Resize Images 拡張機能の場合と同様に、関数ログでトリガーされた関数を確認できます。
保存できる下書きの上限が少なすぎます
カスタマー サポート チームから連絡があり、特に売り上げの多い販売者から、下書きが投稿される前に削除されているという苦情が寄せられました。チームメイトと算数を確認すると、計算の誤差が 10,000 倍になっていることに気が付きました。
この問題を解決するにはどうすればよいですか。インストールした拡張機能を再構成しましょう。
- Firebase コンソールの左側のペインで、[拡張機能] をクリックします。
- インストールした拡張機能のカードの [管理] をクリックします。
- 右上の [拡張機能を再構成] をクリックします。
- [保持するノードの最大数] を
50000
に変更します。 - [保存] をクリックします。
必要な操作はこれだけです。拡張機能の更新には、サポートチームに連絡して、修正がすでにデプロイされていることを伝えることができます。
6. ユーザーデータを自動的に削除する
問題点
カスタマー サポート チームから再度連絡がありました。営業担当者が自分のアカウントを削除したにもかかわらず、まだ他のユーザーからメールが送られてきて、怒っています。これらの販売者は、アカウントを削除するとメールアドレスもシステムから削除されることを想定していました。
当面は、各ユーザーのデータを手動で削除してきましたが、もっといい方法があるはずです。定期的に実行される独自のバッチ ジョブを作成して、削除されたアカウントからメールアドレスを消去することを検討します。しかし、ユーザーデータの削除はよくある問題のように思えます。Firebase Extensions もこの問題の解決に役立つかもしれません。
解決方法
ユーザーがアカウントを削除したときにデータベース内の users/uid
ノードが自動的に削除されるように Delete User Data 拡張機能を構成します。
- 拡張機能の詳細ページで [インストール] ボタンをクリックします。
- Marketplace ウェブアプリに使用している Firebase プロジェクトを選択します。
- [拡張機能を設定する] ステップが表示されるまで、画面上の手順に沿って操作します。
- [Realtime Database のパス] に「
sellers/{UID}
」と入力します。sellers
の部分は、その子にユーザーのメールアドレスが含まれるノードで、{UID}
はワイルドカードです。この構成により、拡張機能は UID が 1234 のユーザーがアカウントを削除したときにデータベースからsellers/1234
を削除する必要があることを認識します。 - [拡張機能をインストール] をクリックします。
インストールの完了を待っている間に...
カスタマイズ性について
この Codelab では、Firebase Extensions が一般的なユースケースの解決に役立ち、アプリのニーズに合わせて拡張機能を構成できることを確認しました。
しかし、拡張機能ですべての問題を解決できるわけではなく、ユーザーデータの削除の問題はその好例です。Delete User Data 拡張機能は、ユーザーがアカウントを削除した後もメールが引き続き公開されるという現在の苦情に対処していますが、この拡張機能によってすべてが削除されるわけではありません。たとえば、アイテムリストは引き続き使用でき、Cloud Storage 内の画像もそのまま残ります。Delete User Data 拡張機能を使用すると、削除する Cloud Storage パスを構成できますが、ユーザーはさまざまな名前の多数のファイルをアップロードできるため、これらのアーティファクトを自動的に削除するようにこの拡張機能を構成することはできません。このような場合には、アプリのデータモデルに固有のコードを記述できるように、Cloud Functions for Firebase のほうが適しています。
拡張機能と課金
Firebase Extensions 自体は無料で使用できます(請求は、使用する基盤リソースに対してのみ発生します)。ただし、拡張機能に必要な基盤となるリソースには課金が必要になる場合があります。この Codelab は、請求先アカウントなしで完了できるように設計されています。しかし、Flame または Blaze のプランを設定することで、非常に興味深い Firebase Extensions を多数利用できます。
たとえば、URL の短縮、メールのトリガー、BigQuery へのコレクションのエクスポートなどが可能です。拡張機能の全カタログについては、こちらをご覧ください。
利用したい拡張機能が現時点で利用できないという場合は、ぜひお知らせください。新しい拡張機能を提案するには、Firebase サポートに機能リクエストを提出してください。
実例を見る
拡張機能のインストールが完了したら、ユーザーを削除してどうなるかを確認します。
- Firebase コンソールで、Realtime Database ダッシュボードに移動します。
sellers
ノードを開きます。- 各販売者の情報は、それぞれのユーザー UID に紐付けられています。ユーザーの UID を選択します。
- Firebase コンソールで [Authentication] ダッシュボードに移動し、そのユーザーの UID を見つけます。
- UID の右側のメニューを開き、[Delete Account] を選択します。
- Realtime Database ダッシュボードに戻ります。販売者の情報は削除されます。
7. お疲れさまでした
この Codelab ではそれほど多くのコードを記述しませんでしたが、Marketplace アプリに重要な機能を追加しました。
拡張機能を検出、構成、インストール、再構成する方法を学習しました。さらに、インストール済みの拡張機能をモニタリングする方法と、必要に応じてアンインストールする方法についても学習しました。
次のステップ
他にも次のような拡張機能があります。
- Cloud Firestore でテキスト文字列を翻訳する(請求先アカウントが必要)
- Mailchimp メーリング リストに新しいユーザーを追加する(請求先アカウントが必要)
- 短縮 URL(請求先アカウントが必要)
サーバー側のカスタムコードがさらに必要な場合は、
その他の参考ドキュメント
拡張機能の管理:
- Firebase CLI で拡張機能を管理してみる
- 予算アラートを設定する
- インストールした拡張機能の実行頻度を確認する
- インストールした拡張機能を新しいバージョンに更新する
- 拡張機能をアンインストールする
拡張機能の詳細: