Firebase Hosting では、Cloud Functions を使用してサーバー側の処理を実行できます。つまり、Firebase Hosting サイトのコンテンツの動的生成をサポートすることができます。できることの例をいくつか紹介します。
- 動的コンテンツの提供。 静的なコンテンツのみを提供するのではなく、動的に生成されたレスポンスを返す関数を通じて、サーバー側のロジックを実行できます。たとえば、
/blog/<id-for-blog-post>のような URL を使用できます。この URL パターンは、URL のブログ投稿 ID パラメータを動的に使用する関数を指して、Firebase Realtime Database からコンテンツを動的に取得することができます。 - SEO を向上させる単一ページアプリを事前レンダリングする。これにより、さまざまなソーシャル ネットワーク間で共有できる動的な
metaタグを作成できます。 - ウェブアプリを軽量に保つ。 Firebase Hosting サイト用の Cloud Functions を使用して API を作成すると、非同期でコンテンツを取得できます。これにより、クライアント コードを軽量に保ち、関数を介して非同期にコンテンツをロードすることで、ウェブアプリの初期ロード時間を短縮できます。
Firebase Hosting には 60 秒のリクエスト タイムアウトが適用されます。生成にかかる時間が 60 秒を超える可能性がある動的コンテンツには、App Engine フレキシブル環境を使用することを検討してください。
Cloud Functions を Firebase Hosting に接続する
関数を Firebase Hosting に接続するには、Cloud Functions の設定、関数の記述、リライトルールの作成、変更のデプロイが必要です。動的コンテンツのパフォーマンスを向上させるために、キャッシュ設定を調整することもできます。
Firebase Hosting 用の Cloud Functions を設定する
Cloud Functions for Firebase をすでに設定している場合は、この手順をスキップして、HTTP 関数の作成に進むことができます。
プロジェクト向けに Cloud Functions を設定するには、Firebase CLI の最新バージョンが必要です。これには Node.js v6.3.1 以降が必要です。Node.js をインストールするには、https://nodejs.org/ で説明されている手順に沿って操作してください。Node.js をインストールすると npm もインストールされます。
インストールした Node.js のバージョンを確認するには、ターミナルで次のコマンドを実行します。
node --version
Firebase CLI の最新バージョンをインストールするには、ターミナルで次のコマンドを実行します。
npm install -g firebase-tools
ローカルマシンを Firebase アカウントに接続し、Firebase プロジェクトへのアクセスを取得するには、次のコマンドを実行します。
$ firebase login
次に、Cloud Functions を初期化する必要があります。
Hosting を使用する Firebase プロジェクトをまだ初期化していない場合は、プロジェクト ディレクトリ内で次のコマンドを実行します。プロンプトが表示されたら、Hosting と Cloud Functions の初期化を選択します。
firebase init
ただし、既存の Firebase プロジェクトで Hosting を使用している場合は、プロジェクト ディレクトリ内で次のコマンドを実行して、Cloud Functions のみを初期化します。
firebase init functions
Hosting サイトに HTTP 関数を作成する
任意のエディタで /functions/index.js を開き、内容を次のコードに置き換えます。このコードでは、bigben という名前の HTTP 関数を作成します。
const functions = require('firebase-functions');
exports.bigben = functions.https.onRequest((req, res) => {
const hours = (new Date().getHours() % 12) + 1 // London is UTC + 1hr;
res.status(200).send(`<!doctype html>
<head>
<title>Time</title>
</head>
<body>
${'BONG '.repeat(hours)}
</body>
</html>`);
});
関数に Hosting リクエストを送信する
リライトルールを使用すると、特定のパターンに一致するリクエストを単一の宛先に送ることができます。たとえば、Hosting サイトの /bigben ページからすべてのリクエストを送信して bigben 関数を実行するには、firebase.json を開き、hosting セクションの下に次の rewrite 構成を追加します。
{
"hosting": {
"public": "public",
// Add the following rewrites section *within* "hosting"
"rewrites": [ {
"source": "/bigben", "function": "bigben"
} ]
}
}
Firebase Hosting には 60 秒のリクエスト タイムアウトが適用されます。そのため、60 秒よりも長いリクエスト タイムアウトを指定して HTTP 関数を構成した場合であっても、関数の実行に必要な時間が 60 秒を超えると、HTTP ステータス コード 504(リクエスト タイムアウト)が返されます。この種類の動的コンテンツをサポートするには、App Engine フレキシブル環境を使用することを検討してください。
詳しくは、リライトルールをご覧ください。
動的コンテンツをローカルで実行する
Firebase CLI を使用すると、動的コンテンツをローカルにデプロイし、実行できます。これにより、本番環境にデプロイする前にサイトをテストできます。
この機能を使用するには、firebase-tools は v3.8.0 以降、firebase-functions SDK は v0.5.7 以降である必要があります。この両方を更新するには、プロジェクトの functions/ ディレクトリで次のコマンドを実行します。
npm install --save firebase-functions@latest
npm install -g firebase-tools
動的コンテンツをローカルで実行するには、firebase serve を使用します。
firebase serve --only hosting,functions # emulates local hosting code and local functions code
firebase serve --only hosting # emulates local hosting code, but uses production functions as proxies
このコマンドで出力された URL を使用すると、Firebase Hosting のコンテンツを表示し、HTTP 関数をテストできます。
デプロイ
関数を作成してリライトルールを設定したら、ターミナルで次のコマンドを実行して Firebase プロジェクトをデプロイします。
firebase deploy
デプロイの後、通常は次のような URL を介して関数にアクセスできるようになります。
https://us-central1-<your-project-id>.cloudfunctions.net/bigben
リライトルールで指定されたパスと一致する Firebase Hosting サイトのすべてのトラフィックは、適切な関数にプロキシされます。
サンプルを試す
すべてがデプロイされたら、自分の Firebase Hosting サイトの /bigben に移動し、実際の動作を確認できます。
https://<your-project-id>.firebaseapp.com/bigben
Cookie の使用
Firebase Hosting と Cloud Functions を併用すると、通常、受信リクエストから Cookie が削除されます。この処理は、CDN キャッシュを効率的に使用するために必要になります。特別な名前の __session Cookie だけが許可され、関数の実行に渡されます。
__session Cookie はキャッシュキーの一部に自動的に組み込まれます。このため、異なる Cookie を持つ 2 人のユーザーは、相手のキャッシュに格納されたレスポンスを受信することはできません。ユーザーの承認に応じて異なるコンテンツを提供する場合にのみ、__session Cookie を使用してください。
キャッシュ動作を管理する
Firebase Hosting は、強力なグローバル CDN を使用して、できる限り高速にサイトが表示されるようにします。Firebase Hosting の静的コンテンツは、コンテンツの新しいバージョンをデプロイするまでキャッシュされます。関数はコンテンツを動的に生成するため、関数によって処理されるリクエストは、デフォルトで CDN にキャッシュされません。アプリのスピードアップと関数の実行コストの削減のために、キャッシュの動作を自分で構成できます。
Cache-Control を設定する
キャッシュ管理に使用する主なツールは Cache-Control ヘッダーです。これを設定することで、コンテンツをキャッシュする期間をブラウザと CDN の両方に伝えることができます。関数では、Cache-Control を以下のように設定します。
res.set('Cache-Control', 'public, max-age=300, s-maxage=600');
上記のヘッダーは 3 つのことを行います。
- キャッシュを
publicとしてマークします。これは、このコンテンツが中間のサーバー(ここでは CDN)によってキャッシュされても問題ないことを示しています。デフォルトでは、Cache-Controlはprivateに設定されており、ユーザーのブラウザのみがキャッシュを制御できます。 max-ageを使用して、コンテンツをキャッシュできる秒数をブラウザに通知します。上記の例では、ブラウザに 5 分間キャッシュするよう指示しています。s-maxageを使用して、コンテンツをキャッシュできる秒数を CDN に通知します。上記の例では、CDN に 10 分間キャッシュするよう指示しています。
max-age の値は、ユーザーが古くなったコンテンツを受け取っても問題ないと思える最大時間に設定します。ページが数秒ごとに変更される場合は、max-age を小さい数にする必要があります。ただし、他のタイプのコンテンツは数時間、数日間、または数か月間、キャッシュできます。
Cache-Control ヘッダーの詳細については、Mozilla Developer Network をご覧ください。
キャッシュされたコンテンツが配信されるタイミング
Cache-Control ヘッダーを public に設定した場合、コンテンツは次の内容に基づいて CDN にキャッシュされます。
- ホスト名
- パス
- クエリ文字列
Varyで指定されたヘッダーの内容
Vary ヘッダーは、レスポンスの内容を決定するうえで、リクエストのどの部分が重要であるかを伝える手段です。ほとんどの場合、これを気にする必要はありません。Firebase Hosting は、一般的な状況に対するレスポンスに適切な Vary ヘッダーが設定されていることを自動的に確認します。これにより、使用しているセッションの Cookie または認証ヘッダーがキャッシュキーの一部になっていることも確認されるため、誤ってコンテンツが漏洩することがなくなります。
高度な利用方法では、その他のヘッダーでキャッシュに影響を及ぼす必要が生じることがあります。その場合は、レスポンスに Vary ヘッダーを設定するだけです。
res.set('Vary', 'Accept-Encoding, X-My-Custom-Header');
これらの設定を使用すると、X-My-Custom-Header ヘッダーが異なる以外は同一である 2 つのリクエストが別々にキャッシュされます。

