Astro 6 移行と Cloudflare アーキテクチャ進化の実録:分離から統合へ、その過程で得た知見とセキュリティ
Note: 本記事は AI アシスタント Gemini との対話を通じて構成・執筆されました。
はじめに
こんにちは。個人開発でポートフォリオサイト motimotinotch.com(Astro + Svelte/React + Cloudflare)を運用しています。
先日、Astro 6.0 へのアップデートに合わせ、インフラ構成を 「Pages + Workers の分離構成」 から 「Workers with Assets による単一構成」 へと刷新しました。
本記事では、なぜ最初は分けていたのか、なぜ統合を決断したのか、そしてその過程で直面した技術的な壁とセキュリティ的な恩恵について詳しく共有します。
1. 原点:なぜ最初は Pages と Workers を分けていたのか?
当初の構想では、フロントエンド(Pages)とバックエンド(Workers)を明確に分離する「BFF (Backend for Frontends)」パターンを採用していました。
- 役割の明確化: Pages は「店舗(UI 表示)」、Workers は「倉庫・作業場(データ処理・R2 操作)」と役割を分けることで、UI の更新と API の開発を独立させ、見通しを良くしようとしていました。
- 当時の技術的標準: 当時は Pages と Workers を組み合わせるのが Cloudflare エコシステムでの王道であり、現在の統合的な「Workers with Assets」はまだ一般化していませんでした。
2. 転換点:Cloudflare Pages で直面した「重大な壁」
Astro 6 への移行を進める中で、この分離構成を維持したまま統合を進めようとしたところ、2つの重大な障壁にぶつかりました。
1042 Loopback エラー
SSR(サーバーサイドレンダリング)実行中に、同じプロジェクト内の API エンドポイント(/api/...)を fetch しようとすると発生するエラーです。Cloudflare Pages の制限により、自身のネットワーク内への自己呼び出しが阻まれ、データの取得ができない状態に陥りました。
「ASSETS」予約語の競合
Astro 6 と Cloudflare Pages の組み合わせにおいて、内部的に使用される ASSETS というバインディング名が競合。静的ファイルの配信やデプロイが困難になるという、予期せぬ仕様の衝突が発生しました。
3. 解決策:Workers with Assets への「戦略的統合」
これらの壁を乗り越えるため、私たちは Pages の利用を断念し、プロジェクト全体を単一の Cloudflare Worker (Workers with Assets) として再定義する決断をしました。
内部サービス層へのリファクタリング
ループバック問題を回避するため、データ取得の仕組みを根本から見直しました。SSR プロセスが自身の API を「HTTP(fetch)経由」で叩くのをやめ、直接 R2 や KV を操作する 「内部サービス層(関数呼び出し)」 を直接実行する形にリファクタリングしました。
4. セキュリティ的恩恵:直接呼び出しがもたらした強固な境界
可用性のために行ったこのリファクタリングは、結果としてシステムのセキュリティ強度を大幅に高めることになりました。
- SSRF (Server-Side Request Forgery) の根絶: 外部(HTTP)という経路を通らず、信頼されたプロセス内での「関数実行」で完結するため、ネットワーク経由の攻撃表面が消滅しました。
- 認証情報の保護: ネットワーク上に認証トークン(Authorization ヘッダー等)を流す必要がなくなり、シークレットの漏洩リスクが極小化されました。
- API 露出の最小化: SSR 専用の強力な操作を、外部に公開された API エンドポイントとして用意する必要がなくなりました。
5. ⚠️ 最後に立ちはだかった罠:SESSION バインディングの不整合
統合が完了し、不要な KV を削除した後に遭遇したのが、削除したはずの KV がデプロイを阻む 「SESSION の幽霊」 現象でした。
Astro 6 の Cloudflare アダプターは、標準のセッション機能をサポートするために SESSION というバインディングを自動的に挿入しようとします。これにより、既に削除した古い KV ID への参照が残り続け、デプロイが拒否される状態(デッドロック)になります。
解決策: wrangler.toml に SESSION バインディングを明示的に定義し、Cloudflare ダッシュボードで「失敗しているロールアウト」を整理することで、不整合をリセットできました。
6. デプロイフローの確立:GitHub Actions による完全自動化
アーキテクチャが Workers に一本化したことで、デプロイ工程も wrangler コマンドベースに刷新し、GitHub Actions で完全に自動化しました。
なぜ Pages の自動ビルドから移行したのか?
Cloudflare Pages の「ソースコードを渡せば自動でビルド・デプロイしてくれる」という手軽さを捨ててまで、なぜ外部 CI である GitHub Actions へ移行したのか。そこには明確な理由がありました。
- ビルドプロセスの完全な制御: 実行環境である Workers (特に Workers with Assets) は、本来ビルド済みの資産をアップロードする形式です。外部 CI を使うことで、Node.js のバージョンやビルド環境を私たちが完璧にコントロールできるようになります。
-
Node.js 22 への対応: 最新の Wrangler v4.87.0 以上では Node.js 22 が必須となりました。GitHub Actions で
actions/setup-node@v4を使い、明示的に Node.js 22 環境でビルドを行うことで、環境不一致によるビルドエラーのリスクを排除しました。 - Workers with Assets への適合: ビルドされた静的資産と API ロジックを一つのパッケージとして確実に送り届けるために、Wrangler コマンドを直接叩ける CI ワークフローが最適解でした。
wrangler-action の活用
これまで Cloudflare Pages の管理画面側で行われていたビルド・デプロイ工程を、cloudflare/wrangler-action を使った GitHub Actions ワークフローへ移行しました。
-
プレビュー環境:
developブランチへの push または PR 作成時に、moti-portfolio-previewという名前で自動デプロイ。 -
本番環境:
mainブランチへのマージをトリガーに、moti-portfolioという名前で自動デプロイ。
これにより、環境ごとのバインディング(接続する KV や R2)を wrangler.toml と GitHub の環境変数で明示的に制御できるようになり、インフラ構成の透明性が Pages 時代よりも格段に向上しました。
7. 運用の高度化:メンテナンスもスリムに
インフラがクリーンになったことで、運用の手間も削減されました。
- GitHub Actions への移譲: 毎日実行していたクリーンアップ処理を、リソース節約のため 毎月1日 実行に変更し、Actions から API を叩く形式に一本化。Cloudflare 側の Cron 設定を廃止しました。
まとめ:進化した「綺麗な基地」
Astro 6 への移行は、単なるライブラリの更新ではなく、Cloudflare エコシステムの進化に合わせたアーキテクチャの進化 でした。
「店舗」と「倉庫」をひとつに統合したことで、管理は容易になり、パフォーマンスとセキュリティは向上しました。
この記事が、同様の移行やアーキテクチャ設計に悩む方々の助けになれば幸いです。
Discussion