このページで分かること

  • オブジェクトキャッシュの役割(リクエストをまたいで取得結果を保持し、正本は引き続きデータベース)と、2つの保存先(KV、メモリー)の違い
  • Cloudflare KVとNode.jsのメモリーそれぞれの設定方法と設定項目
  • キャッシュされるもの、編集したときに無効になる範囲と反映までの時間、予約公開したエントリーが反映されるタイミング
難易度
実践
読む時間
4分
このページの目次

EmDashのリクエスト単位のキャッシュは、1回のページの描画の中で同じ読み込みが重複しないよう、すでにまとめています。任意で使えるオブジェクトキャッシュ(object cache)は、選んだ取得結果をリクエストをまたいで保持し、あとのリクエストが同じデータベースの読み込みをしなくて済むようにします。公開サイトへのトラフィックによって、選んだデータベースが処理すべき量を超える読み込みが発生する場合に役立ちます。

正本は引き続きデータベースです。キャッシュの読み込みに失敗した場合はデータベースから読み込み(フェイルオープン)、書き込みがあると影響を受けるキャッシュの名前空間が無効になります。オブジェクトキャッシュはデフォルトで無効です。有効にするには、emdash() インテグレーションに objectCache アダプターを追加します。

概要

バックエンド 向いている環境 isolate間での共有
KV Cloudflare Workers あり
メモリー Node.js、ローカルでの開発 なし(プロセスごと)

Cloudflareでは、リクエストは各地域にある短時間だけ動く多数のisolateで処理されます。KVはそのすべてから共有されるため、あるリクエストでキャッシュした値を、どこで処理される次のリクエストでも使えます。メモリーのバックエンドは1つのプロセスの中でキャッシュするため、長時間動き続けるNode.jsのサーバーに向いています。

本サイトの補足 やさしい解説

WordPressでページを開くたびにデータベースから記事を読み込むのと同じく、EmDashもページを描画するたびにデータベースから読み込みます。オブジェクトキャッシュは、一度読み込んだ結果を取っておき、次のリクエストではデータベースの代わりにそれを返す仕組みです。デフォルトでは無効で、アクセスが多くデータベースの読み込みを減らしたいときに追加します。Cloudflare Workersでは、処理する場所(isolate)がリクエストごとに変わるため、全体で共有できるKVを使います。1台で動き続けるNode.jsのサーバーでは、メモリーに保存します。

Cloudflare KV

KVアダプターを設定し、KVバインディングを指定します。

astro.config.mjs
import emdash from "emdash/astro";
import { d1, r2, kvCache } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			database: d1({ binding: "DB" }),
			storage: r2({ binding: "MEDIA" }),
			objectCache: kvCache({ binding: "CACHE" }),
		}),
	],
});

セットアップ

KVの名前空間を作成し、Wranglerの設定にバインディングを追加します。

npx wrangler kv namespace create CACHE

コマンドを実行すると、名前空間の id が表示されます。kvCache で使ったバインディング名の下に、その id を追加します。

wrangler.jsonc

{
  "kv_namespaces": [
    {
      "binding": "CACHE",
      "id": "<namespace-id>"
    }
  ]
}

wrangler.toml

[[kv_namespaces]]
binding = "CACHE"
id = "<namespace-id>"

オプション

オプション デフォルト 説明
binding string Wranglerの設定に書いたKVバインディングの名前。必須です。
defaultTtl number 3600 キャッシュしたエントリーの有効期間(秒)。KVでは最小60秒です。
revalidate number 1000 isolate内でエポックを再利用する時間幅(ミリ秒)。反映までの時間を参照してください。
timeout number 2000 KVの操作を待つ最大時間(ミリ秒)。これを超えるとキャッシュミスとして扱います。KVの読み込みが止まったときに、リクエストが応答しなくなるのを防ぎます。0 を設定すると無効になります。
keyPrefix string "em" すべてのキャッシュキーに付けるプレフィックス。複数のサイトで1つの名前空間を共有する場合は、サイトごとに異なる値を設定します。

Node.js(メモリー)

メモリーのアダプターは、サーバーのプロセスの中でキャッシュします。外部のサービスは必要ありません。

astro.config.mjs
import emdash, { memoryCache } from "emdash/astro";
import { sqlite } from "emdash/db";

export default defineConfig({
	integrations: [
		emdash({
			database: sqlite({ url: "file:./data.db" }),
			objectCache: memoryCache(),
		}),
	],
});

オプション

オプション デフォルト 説明
defaultTtl number 3600 キャッシュしたエントリーの有効期間(秒)。
revalidate number 1000 isolate内でエポックを再利用する時間幅(ミリ秒)。
maxEntries number 1000 キャッシュするキーの最大数。これを超えると古いキーから削除されます。
keyPrefix string "em" すべてのキャッシュキーに付けるプレフィックス。

キャッシュされるもの

オブジェクトキャッシュの対象は、一般的なページの描画で実行される読み込みです。

  • コンテンツの取得:getEmDashCollectiongetEmDashEntryresolveEmDashPath
  • サイト設定、ナビゲーションメニュー、タクソノミーのターム

管理画面のAPIへのリクエスト、メディアファイル、HTMLのレスポンス全体は、ここでは扱いません。描画したHTMLをエッジでキャッシュする方法は、Cloudflareへのデプロイを参照してください。

オブジェクトキャッシュとHTMLのエッジキャッシュは、別々の問題を解決します。HTMLの層でキャッシュミスになった場合もWorkerは実行されますが、そのときオブジェクトキャッシュがあれば、コンテンツの取得の繰り返しを防げます。HTMLの層でキャッシュヒットした場合は、EmDashはまったく実行されません。

反映までの時間

管理画面またはREST APIでコンテンツを編集すると、影響を受けるキャッシュのエントリーは自動で無効になります。エントリーを作成、更新、公開、削除すると、そのコレクションのキャッシュ済みの取得結果が消去されます。バイラインやタクソノミーのタームを変更すると、それを表示しているエントリーのキャッシュが消去されます。

匿名の訪問者に対しては、各isolateが更新されたエポックを受け取るまで、変更がすべてのisolateに反映されるのに時間がかかります。isolate内のメモリーのバックエンドでは、すぐに反映されます。Workers KVでは、KVのエッジキャッシュの伝播(結果整合性で、最大60秒程度)に、isolate内の revalidate の時間幅(デフォルトは1秒)を足した時間までかかります。revalidate を小さくすると、キャッシュへの読み込みが増える代わりに、isolate内での反映が速くなります。大きくすると、キャッシュを読み込む回数が減ります。

予約公開したコンテンツ

予約公開したエントリーは、公開日時を過ぎると表示されるようになります。キャッシュされたページに、新しく公開された予約公開のエントリーが反映されるのは、そのコレクションに次の変更があったとき、またはキャッシュしたエントリーの defaultTtl が切れたときです。予約公開の時刻どおりに表示されることがサイトにとって重要な場合は、defaultTtl を小さく設定します。

本サイトの補足 やさしい解説

WordPressでは、予約投稿は公開日時になると表示されます。EmDashでオブジェクトキャッシュを使っている場合、予約公開のエントリーは公開日時を過ぎても、すぐには表示されないことがあります。表示されるのは、同じコレクションで別の変更があったときか、キャッシュの有効期間(defaultTtl、デフォルトは3600秒=1時間)が切れたときです。時刻どおりに表示したい場合は、defaultTtl を短くします。