開発
Cloudflare Durable Objectsを使用してレイテンシーを最適化するデプロイを実現する
Astro+Sanity+Cloudflare Pages の静的サイトで増加するコンテンツによりビルドが遅延する問題を、Cloudflare Workers と Durable Objects を組み合わせた「汎用 Webhook 遅延トリガー」で解決する方法を紹介。ビルドリクエストを一定時間まとめて1回にし、複数プロジェクトで共用可能。
- #Cloudflare Durable Objects
- #Webhook遅延トリガー
- #静的サイトビルド最適化
- #Astro Sanity連携
25
以前にあるプロジェクトを作ったことがあります。個人サイトタイプのコンテンツサイトだったため、完全な静的サイトの構成を選択し、フレームワークには Astro を、CMS には Sanity を使用しました。プロジェクトは Cloudflare Pages にデプロイし、Sanity 側で設定を行い、コンテンツに変更があった際に再ビルドをトリガーする webhook を発火させるようにしました。
しかし、コンテンツが増えるにつれて(あるタイプのコンテンツが600件以上ある)、ビルド時間もそれに伴って長くなり、毎回のビルドには最大で7分もかかるようになりました。さらに、Sanityは手動でwebhookをトリガーすることをサポートしていないため、もし記事を数回保存すると、その回数分だけビルドが実行されてしまいます。大量の無駄なデプロイが発生するだけでなく、時間も非常にかかります。もし十数本の記事を修正した場合、最新の内容を確認するまでに1時間も待たなければなりません。
だから、今年このプロジェクトの新機能を作るときに、遅延ビルドのことも考慮に入れました。
この機能はとてもシンプルです。Webhook の中継として動作し、ビルドリクエストを受け取ったら、一定時間遅らせてから送信します。その間に新しいリクエストが来た場合は、タイマーをリセットします。遅延時間が 20 分の場合、どれだけ設定を変更しても、変更と変更の間隔が 20 分を超えない限り、実際のビルドは 1 回だけです。
私の方針は、できるだけサーバーとやり取りをしないことなので、この要件を可能な限り Cloudflare 上で実現したいと考えています。
worker だけでは不十分です。worker はステートレスなので、単純に setInterval を使うことはできません。いろいろと調べた結果、Durable Objects を使えばこの要件を実現できることが分かりました。
このドキュメントで、Cloudflare は Durable Objects を将来のある時点に起動する方法を紹介しています。
さらに、getByName(“scheduler”) を通じてこれらのトリガーイベントが同じインスタンスを取得するようにすることもできます。新しいリクエストは以前のリクエストを上書きするため、重複したビルドは発生しません。
より汎用的にするために、ターゲットの webhook リンクを固定せず、HTTP ヘッダーとして渡すようにしました。同時に、遅延時間や検証用トークンも受け付けます。これにより、複数プロジェクトで共用できる汎用的な webhook 遅延トリガーになりました。
詳細なコードと使用方法はGitHubを参照してください。