Cloud Functions による動的コンテンツの配信

Firebase Hosting では、Cloud Functions を使用してサーバー側の処理を実行できます。つまり、Firebase Hosting サイトのコンテンツの動的生成をサポートすることができます。できることの例をいくつか紹介します。

  • 動的コンテンツの提供。静的なコンテンツのみを提供するのではなく、動的に生成されたレスポンスを返す関数を通じて、サーバー側のロジックを実行できます。たとえば、/blog/<id-for-blog-post> のような URL を使用できます。この URL パターンは、URL のブログ投稿 ID パラメータを動的に使用する関数を指して、Firebox Realtime Database からコンテンツを動的に取得することができます。
  • SEO を向上させる単一ページアプリの事前レンダリング。これにより、さまざまなソーシャル ネットワーク間で共有できる動的な meta タグを作成できます。
  • ウェブアプリを軽量に保つ。Firebase Hosting サイト用の Cloud Functions を使用して API を作成すると、非同期でコンテンツを取得できます。これにより、クライアント コードを軽量に保ち、関数を介して非同期にコンテンツをロードすることで、ウェブアプリの初期ロード時間を短縮できます。

Cloud Functions を Firebase Hosting に接続する

関数を Firebase Hosting に接続するには、Cloud Functions の設定、関数の記述、リライトルールの作成、変更のデプロイが必要です。動的コンテンツのパフォーマンスを向上させるために、キャッシング設定を調整することもできます。次の例ではその方法を紹介します。

Firebase Hosting 用の Cloud Functions を設定する

Cloud Functions for Firebase をすでに設定している場合は、この手順をスキップして、HTTPS 関数の作成に進むことができます。これにより Firebase プロジェクト用の Cloud Functions が設定されます。

まず、Firebase CLI の最新バージョンを使用していることを確認してください。これには Node.js バージョン 6.3.1 以降が必要です。Node をインストールするには https://nodejs.org/ の手順を参照してください。Node.js をインストールすると npm もインストールされます。

実行している Node.js のバージョンを確認するには、端末で次のコマンドを実行します。

node --version

端末で次のコマンドを実行すると、Firebase CLI の最新バージョンをインストールできます。

npm install -g firebase-tools

Firebase CLI を更新したら、関数を初期化する必要があります。Hosting プロジェクトを初期化していない場合は、次のコマンドを実行し、プロンプトが表示されたらプロジェクト ディレクトリ内で Hosting と Cloud Functions の初期化を選択します。

firebase init

既存プロジェクトで Hosting を使用している場合は、プロジェクト ディレクトリ内で次のコマンドを実行して、Cloud Functions のみを初期化します。

firebase init functions

Hosting サイトに HTTP 関数を作成する

任意のエディタで /functions/index.js を開き、内容を次のコードに置き換えます。これで bigben という簡単な HTTPS 関数が作成されます。

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 CLI を使用すると、動的コンテンツをローカルにデプロイし、実行することができます。これにより、本番環境にデプロイする前にサイトをテストできます。

この機能を使用するには、firebase-tools のバージョン 3.8.0 以降と firebase-functions SDK のバージョン 0.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 分間キャッシュするよう指示しています。

maxage を設定するときは、ユーザーが古くなったコンテンツを受け取っても問題ないと思える最大時間に設定する必要があります。ページが数秒ごとに変更される場合、これは小さい数になります。ただし、他のコンテンツは数時間、数日間、または数か月間、キャッシュすることができます。

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 つのリクエストが、別々にキャッシュされるようになりました。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。