Storefront の Cloudflare Workers デプロイ手順¶
目的¶
リツビ B2B Storefront(Vite + TanStack Router)を Cloudflare Workers + Static Assets で配備するための、GitHub Actions 前提の運用手順、設定ファイル、環境変数管理、既知の注意点を整理する。
1. 事前準備¶
- Cloudflare アカウントで Workers を利用可能であること
- local で Cloudflare 設定変更を行う
wrangler実行は、共有 token 注入ではなくwranglerのユーザー認証を正として運用する pnpmワークスペースにwranglerを追加済み- Vendure 本番 API エンドポイントが稼働し、Workers からのアクセスが許可されていること
- CI からデプロイする場合も Cloudflare 認証情報は GitHub secret へ複製せず、AWS
Secrets Manager の
*_sharedを正本として使う - Cloudflare Dashboard の Workers Builds で対象 Worker と GitHub リポジトリ連携を作成済みであること
worker.jsが request entrypoint:ASSETSbinding で静的配信を行い、/assets/*やfavicon.icoのような ファイルリクエストはそのまま返し、その他は SPA fallback として/を返す。 過去の OpenNext 運用で作成された Durable Object class (DOShardedTagCache/DOQueueHandler/BucketCachePurge) は Cloudflare 側の worker metadata に残るため、Vite 移行後もworker.jsでは互換 stub export を維持する。これを消すとwrangler versions uploadがcode: 10064で拒否される。- Worker API は
src/worker-api.tsを正本にする:/commerce/*・/api/*・health 系 endpoint は browser app から切り離した Worker 側 handler で処理する。 - production / staging / preview / mock は同じ Vite build を使う:
環境差分は
wrangler.tomlの env table と deploy 時の runtime vars / secret 注入で吸収する。 - メンテナンス状態は
MAINTENANCE_KVbinding を正本にする:scripts/cloudflare-deploy.mjsが target ごとの namespace を temporary config へ注入してからwrangler versions upload/deployを実行する。
2. 新規追加・更新した主なファイル¶
| ファイル | 役割 |
|---|---|
apps/storefront/wrangler.toml |
Workers 用設定(ASSETS binding / env 別 observability / vars) |
apps/storefront/worker.js |
SPA fallback と Worker API への分岐を行う Worker entrypoint |
apps/storefront/scripts/cloudflare-build.mjs |
Vite build 済み dist/ を検証する Cloudflare build 補助 |
apps/storefront/scripts/cloudflare-deploy.mjs |
Wrangler versions upload/deploy と MAINTENANCE_KV 注入を行う deploy script |
apps/storefront/worker-configuration.d.ts |
wrangler types 生成の型定義 |
.github/workflows/ci-push-develop.yml |
develop への push 後の統合 CI ゲート |
.github/workflows/deploy-staging.yml |
手動起動で staging の Vendure / Worker / Dashboard をデプロイ |
.github/workflows/deploy-production.yml |
main への push で production Worker へ自動デプロイ |
.github/workflows/workers-secrets-sync.yml |
GitHub Actions による AWS Secrets Manager → Workers secrets 同期(手動実行・緊急用途) |
.github/workflows/workers-version-deploy.yml |
GitHub Actions による Workers version の手動再デプロイ |
(廃止)apps/storefront/scripts/generate-content.cjs |
ダミー記事・キャンペーン生成は 2025-11 に廃止済み。現在は使用しない |
手動の version 再デプロイは gh workflow run を直接叩くより、run 追跡まで含めて just レシピを使う。
just manual-deploy-storefront-version environment=staging version_ref=<commit_sha>
just manual-deploy-storefront-version environment=production version_ref=<commit_sha>
just manual-deploy-storefront-version environment=production version_ref=<workers_version_uuid>
version_ref は UUID 形式(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)なら Workers version ID として直接使い、それ以外は commit sha として tag 検索する。version_ref は必須。
3. 環境変数の整理¶
Workers の設定値は大きく 2 種類に分けて扱う。
- Secrets(機密): GitHub Actions の deploy workflow が AWS Secrets
Manager から取得し、
wrangler secret bulkで Workers 側へ投入する(shared + storefrontをマージして投入)。通常は deploy と同時実行。workers-secrets-sync.ymlは手動同期の非常用)。CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDも AWS Secrets Manager から読み、GitHub secret を Cloudflare 正本としては扱わない - Vars(非機密):
wrangler.tomlの[vars]や Cloudflare ダッシュボードの Variables で管理する
| 変数名 | 用途 | 備考 |
|---|---|---|
VENDURE_BASE_URL |
Vendure 基本URL(例: https://api.example.com) |
必須。これを基準に各APIパスが自動解決される |
VENDURE_API_URL |
Shop GraphQL フルURL(/shop-api を含む) |
非推奨。原則 VENDURE_BASE_URL から自動生成 |
VENDURE_ASSET_URL |
Vendure 商品画像の公開ベースURL | ec-assets に分離する場合は設定を推奨 |
STOREFRONT_DEPLOY_TARGET |
Worker runtime の deploy target | production / staging / preview / mock |
VITE_PUBLIC_STOREFRONT_DEPLOY_TARGET |
client 側で参照する deploy target | public config へそのまま流し込む |
VITE_PUBLIC_STOREFRONT_API_MOCKING |
disabled 固定 |
本番では MSW を無効化 |
VITE_PUBLIC_WORDPRESS_ASSET_BASE_URL |
WordPress画像の配信ベースURL | 例: https://wp-assets.example.com |
VITE_PUBLIC_ASSET_HOSTS |
Storefront が参照する公開 asset host 群(CSV) | wp-assets.example.com を含める |
CLOUDFLARE_ACCESS_CLIENT_ID |
Cloudflare Access service token client id | WordPress が Zero Trust 配下の場合に使用 |
CLOUDFLARE_ACCESS_CLIENT_SECRET |
Cloudflare Access service token client secret | WordPress が Zero Trust 配下の場合に使用 |
MAINTENANCE_KV |
Storefront メンテナンス状態の KV binding | storefront:maintenance キーを参照 |
MAINTENANCE_KVは通常の Variables ではなく KV binding。Storefront deploy ではapps/storefront/scripts/cloudflare-deploy.mjsがCLOUDFLARE_MAINTENANCE_KV_NAMESPACE_IDを一時 Wrangler config へ注入し、wrangler versions upload→wrangler versions viewで binding 検証 →wrangler versions deployの順で反映する。現在の Storefront Worker は
wrangler.tomlのsecrets.requiredを使っていない。 experimental warning を避けるため、runtime secret の存在確認は deploy 時のwith-cloudflare-auth.sh/cloudflare-deploy.mjsと環境側の secret 正本で担保する。
wrangler.tomlではMAINTENANCE_KVplaceholder を production は top-level table 群の前、 staging / preview / mock は各[env.<target>]の前に置き、生成される binding が 期待どおりの TOML scope に入るようにする。既存 Worker が過去の Durable Object class を保持している環境では、
wrangler versions uploadがNew version of script does not export class ...で失敗することがある。その場合はapps/storefront/worker.jsから該当 class export を消していないか確認し、明示的な delete-class migration を設計するまでは互換 stub を残す。WordPress が Cloudflare Access(Zero Trust)で保護されている場合は、Storefront/Vendure の上流 CMS 通信に
CF-Access-Client-Id/CF-Access-Client-Secretヘッダーを付与して疎通する。
3.3 Storefront メンテナンスモード(Cloudflare KV)¶
Storefront のメンテナンスモードは Cloudflare KV を正本とする。
- KV key:
storefront:maintenance - Value JSON:
{
"enabled": false,
"bypassToken": "32charhex",
"updatedAt": "2026-03-11T00:00:00.000Z"
}
MAINTENANCE_KVbinding はapps/storefront/scripts/cloudflare-deploy.mjsが target 環境のCLOUDFLARE_MAINTENANCE_KV_NAMESPACE_IDから生成し、未設定なら deploy を失敗させる。- deploy script は upload 後に
wrangler versions viewでMAINTENANCE_KV(kv_namespace) の存在を確認し、欠けている version は live へ切り替えない。 - Production / staging / preview / mock はそれぞれ別 namespace を使う。
- namespace はメンテナンス専用ではなく、Storefront 固有のランタイム設定ストアとして確保する。
- ec project 全体で単一 namespace を共有せず、共有が必要になった時点で別途
ec-shared-configを切り出す。 scheduleWindowsを設定する場合、時刻は UTC ではなく JST(Asia/Tokyo) の日次時刻として解釈される。詳細な payload 形式、日跨ぎ窓、回帰テストはdocs/05-delivery/maintenance/storefront-maintenance-kv-runbook.mdを参照する。- 初回デプロイ後、namespace ID は target 環境の
*_sharedsecret に設定し、Storefront deploy と Vendure 制御面の両方で共有する。
namespace 作成は次の just レシピで行える。
just cloudflare-maintenance-kv-create production
just cloudflare-maintenance-kv-create staging
命名規約:
- production:
ec-storefront-config - staging:
ec-storefront-staging-config - preview:
ec-storefront-preview-config - mock:
ec-storefront-mock-config
Storefront deploy / Vendure 制御面では次の Secret を設定する。
CLOUDFLARE_ACCOUNT_IDCLOUDFLARE_MAINTENANCE_KV_NAMESPACE_IDCLOUDFLARE_API_TOKEN
CLOUDFLARE_API_TOKEN は対象 namespace の read /
write のみ許可する最小権限トークンに限定する。
3.2 WordPress アセット配信(Cloudflare)¶
WordPress 本文内の wp-content/uploads
を高速配信するため、アセット専用サブドメインを Cloudflare 配下に置く。
- DNS
cms-assets.<domain>を WordPress media 用 R2 配信先へ CNAMEproxied=true(オレンジクラウド)で有効化- Cloudflare Cache Rules
- 対象:
cms-assets.<domain>/wp-content/uploads/* - キャッシュTTLを長めに設定(更新頻度に応じて数日〜数週間)
- Storefront 環境変数
storefrontsecret にVITE_PUBLIC_WORDPRESS_ASSET_BASE_URL=https://cms-assets.<domain>sharedsecret のVITE_PUBLIC_ASSET_HOSTSにcms-assets.<domain>を追加VITE_PUBLIC_ASSET_HOSTSはec-assets.<domain>,cms-assets.<domain>のように両方を持たせる- Storefront deploy
- secret 更新後に
just cloudflare-deploy-storefront production production_storefrontまたはjust deploy-storefront-staging staging_storefrontを実行 VITE_PUBLIC_ASSET_HOSTSをstorefront側へ重複定義すると deploy 時に duplicate key error になるため、正本はsharedに統一する
WordPress 側の offload 設定、既存メディア移行、R2 検証は wordpress-media-offload.md を参照してください。
3.2.1 Vendure アセット配信(Cloudflare)¶
商品画像を API ドメインと分離する場合は、Vendure の public asset URL を専用サブドメインへ向ける。
- DNS
ec-assets.<domain>を Vendure asset 配信先へ向ける- Storefront / Vendure 環境変数
VENDURE_ASSET_URL=https://ec-assets.<domain>- 運用原則
- Storefront の commerce API は
VENDURE_BASE_URL - 商品画像だけ
VENDURE_ASSET_URL - CMS の
wp-content/*はVITE_PUBLIC_WORDPRESS_ASSET_BASE_URL
3.2.2 Storefront 画像変換方針(Cloudflare-first)¶
Storefront の商品画像 / CMS 画像は、production のみ Cloudflare Transformations を使う。
- production
- Storefront は
/cdn-cgi/imageを使って商品画像 / CMS 画像 / 本文内画像 / metadata 画像を配信する - Storefront の画像表示はレイアウト側で
sizes/ lazy-load / preload / CLS 抑制を担い、実変換は Cloudflare を正本とする - local / staging / preview / mock
- Cloudflare Transformations を使わず、raw asset を pass-through する
- 非本番で Cloudflare の変換枠を消費しない
- Vendure の責務
- origin asset 配信と asset metadata 管理に限定する
- Storefront 表示面の fallback として Vendure preset 変換を使わない
- 除外対象
- SVG / GIF / 動画 / PDF などは変換せず pass-through する
- Vendure の React Dashboard / 管理画面には Storefront 用の Cloudflare 画像最適化を適用しない
3.3 Storefront edge delivery の責務¶
Cloudflare は 公開配信の edge delivery を担い、production の商品画像 / CMS 画像では Transformations も含めて扱う。一方で、アプリ内部の共有状態は Redis / Vendure 側へ寄せる。
- Cloudflare に載せるもの
/assets/*、/favicon.ico、/manifest.jsonなどの静的配信- production の
/cdn-cgi/image/*による商品画像 / CMS 画像 / 本文内画像 / metadata 画像 cms-assets.<domain>/wp-content/uploads/*のような公開アセット- 認証非依存で、アプリ側が
Cloudflare-CDN-Cache-Controlを返す公開 GET - Cloudflare に載せないもの
/commerce/shop-api/api/customer-hierarchy/api/revalidate/cms/api/health/live/api/health/ready/api/version/version/api/health/cms(diagnostic only: continuous probe には使わない)- Cookie / Authorization に依存するレスポンス全般
運用ルール:
- HTML / JSON を Cloudflare で積極的にキャッシュしたい場合は、Cache Rules を対象 URL 単位で限定する
/api/*への広いCache Everythingは禁止- session、WordPress snapshot、Vendure shared cache は Cloudflare ではなく Redis 側で扱う
- staging も Redis ありで運用し、本番と同じキャッシュ経路を通す
- staging / local / preview / mock の画像は raw asset pass-through を正本とし、Cloudflare 変換枠を使わない
- Storefront Worker は response hardening として HTTPS 応答に
Strict-Transport-Security: max-age=31536000、全応答にX-Content-Type-Options,Referrer-Policy,X-Frame-Options,Permissions-Policyを付与し、HTML は追加でContent-Security-Policyを返す - staging / preview / mock / local は
X-Robots-Tag: noindex, nofollow, noarchiveを返し、/robots.txtもDisallow: /を返す
3.1 カスタムドメイン運用(Storefront)¶
- Cloudflare 管理ドメイン(SSOT):
order.ritsubi-platform.com - 限定公開ドメイン:
medical.ritsubi.co.jp(2026-05-25〜) - 本番想定の既存公開ドメイン(並行運用):
order.ritsubi.co.jp
Storefront の canonical URL / public alias URL の repo 内 SSOT は
scripts/ops/deploy-targets.sh です。AWS Secrets Manager は機密値の正本であり、
公開 alias URL の主正本にはしません。
medical.ritsubi.co.jp は Cloudflare for SaaS 経由の限定公開 CNAME として運用し、DNS 側で
order.ritsubi-platform.com へ CNAME します。
本番運用上の既存公開先である order.ritsubi.co.jp は引き続き並行運用のため残しつつ、
新規の本番公開先としては order.ritsubi-platform.com を正本にします。
Cloudflare Workers のルートとカスタムドメインは order.ritsubi-platform.com
を使用し続けます。medical.ritsubi.co.jp は運用上のドメイン・UI 公開入口であり、
Workers のルーティング定義を変更しないのが原則です。
Storefront Worker から Vendure へ送る server-to-server リクエストでは、
medical.ritsubi.co.jp などの alias domain を Origin / Referer
として上流へ渡しません。ブラウザから Worker への same-origin 検証はアクセス元の
host で行い、Worker から Vendure への upstream request は
VITE_PUBLIC_SITE_URL / SITE_URL の canonical origin
(production では https://order.ritsubi-platform.com)へ正規化します。
このルールは auth handler と /commerce/shop-api proxy の両方に適用します。
Workers ルート設定(Terraform)¶
order.ritsubi-platform.com/* を ec-storefront
にルーティングする。DNS レコードは Workers 側で管理されるため、同ホストの A/AAAA 追加は不要。
worker_routes = {
order = {
pattern = "order.ritsubi-platform.com/*"
script = "ec-storefront"
}
}
4. ローカルビルドフロー(現行 Vite 実装)¶
備考: 旧 storefront 実装は 2026-05 に削除されました。現在の正本は
apps/storefront(Vite) です。
5. Cloudflare Workers へのデプロイ¶
GitHub Actions + Wrangler Versions(現行構成)¶
本リポジトリでは、Storefront の production / staging / preview / mock
deploy は GitHub Actions(deploy-production.yml / deploy-staging.yml →
_deploy-storefront-workers.yml)および local の cloudflare:deploy* から
apps/storefront/scripts/cloudflare-deploy.mjs を実行する。
deploy script の責務:
CLOUDFLARE_MAINTENANCE_KV_NAMESPACE_IDを temporarywrangler.tomlへ注入する- production は
[[kv_namespaces]]、staging / preview / mock は[[env.<target>.kv_namespaces]]を使って binding の scope を合わせる wrangler versions uploadで新しい Worker version を作成するwrangler versions viewで upload 済み version にMAINTENANCE_KVbinding があることを検証する- 検証済み version のみ
wrangler versions deployで live へ切り替える
ステージングは wrangler.toml の [env.staging]
で Workers 名を分けており、本番とは別 Workers として管理される。
加えて、ci-push-develop.yml では通常の build に加えて
nx affected --target=cloudflare:build
を実行し、Vite/Wrangler 経路の破損をデプロイ前に検知する。CI の差分検知と
local の単体実行は役割が異なるが、どちらも同じ Nx target を通す。
必要に応じて、Workers Builds の Build watch paths で次を対象に設定する。
apps/storefront/**packages/**pnpm-lock.yamlpnpm-workspace.yamlnx.json
ローカル(手動)¶
- Workers へデプロイ
pnpm exec nx run ritsubi-storefront:cloudflare:deploy
- 本番用:
pnpm exec nx run ritsubi-storefront:cloudflare:deploy - staging 用:
pnpm exec nx run ritsubi-storefront:cloudflare:deploy:staging - プレビュー用:
pnpm exec nx run ritsubi-storefront:cloudflare:preview(ローカル開発用) - プレビュー環境デプロイ:
pnpm exec nx run ritsubi-storefront:cloudflare:deploy:preview - mock 環境デプロイ:
pnpm exec nx run ritsubi-storefront:cloudflare:deploy:mock cloudflare-deploy.mjsは barewrangler deployを直接使わず、wrangler versions upload→ binding 検証 →wrangler versions deployの順で反映するcloudflare:deploy*はscripts/ops/with-cloudflare-auth.shを通じて AWS Secrets Manager 正本のCLOUDFLARE_API_TOKENを自動注入する deploy 自動化導線として扱う- 一方で、local で version 一覧確認・手動 rollback・Workers 設定確認など Cloudflare の状態を直接調べる
wrangler操作は、repo 内の writableXDG_CONFIG_HOMEに対するwrangler login/wrangler whoamiによるユーザー認証を正とし、deploy 用 token 注入に寄せない - 手元確認の基本導線は、事前に同じ
XDG_CONFIG_HOMEで認証済みであることを前提にjust cloudflare-whoami→just cloudflare-versions productionの順とする just cloudflare-deploy-storefront <env>/just cloudflare-verify-storefront <env> token/just cloudflare-deployments-status <env>が Cloudflare APIAuthentication error [code: 10000]/ 403 で失敗する場合は、まず同じ wrapper 経由のjust cloudflare-whoamiで OAuth user が対象 account に所属しているか確認する。 account membership / Wrangler authentication の修正を恒久対応とし、緊急反映ではCLOUDFLARE_ALLOW_TOKEN_FALLBACK=1を同じ標準入口に付けて Secrets Manager token fallback を明示的に使う。- local の build / preview / deploy も例外を作らず Nx target を正本にする
Secrets 同期(手動)¶
機密情報(Workers secrets)は、次の workflow を手動実行して同期する。
.github/workflows/workers-secrets-sync.yml:workflow_dispatchでproduction/staging/previewを指定
バージョン再デプロイ(手動)¶
Workers version の再デプロイ/ロールバックは次の workflow を手動実行する。
.github/workflows/workers-version-deploy.yml:version_ref(必須)を指定- UUID 形式なら Workers version ID として直接使う
- それ以外は commit sha として tag 検索する(
vite-prod-{shortsha}タグに substring マッチ) - workflow は対象 version の
MAINTENANCE_KVbinding を検証し、欠けている version の promote を拒否する
注意:
wrangler secret bulkと Gradual Deployments の副作用Cloudflare Workers が Gradual Deployments モードの場合、
wrangler secret bulkを実行すると 暗黙的に新しい Worker version が作成される。この version にはcloudflare-deploy.mjsの TOML 注入が適用されないためMAINTENANCE_KVbinding が欠けた状態になり、workers-version-deploy.ymlの binding チェックで拒否される。このため、production 環境の通常デプロイフローでは
wrangler secret bulkを実行しない。 secrets はPrepare Production Storefront Versionworkflow で 込みのバージョンとしてビルド・事前 upload 済みのため、 production deploy job のSync Workers secretsステップは production では skip される。 secrets のみを緊急で更新する場合は.github/workflows/workers-secrets-sync.ymlを手動実行するのではなく、通常デプロイを再実行するか、Cloudflare Dashboard から直接更新する。
メンテナンス用 KV の直接操作¶
Cloudflare Dashboard もしくは API / CLI から storefront:maintenance
キーを直接更新してよい。詳細手順は
Storefront メンテナンス運用 Runbook
を参照する。
-
デプロイ後に確認すべきポイント
-
/commerce/*リライトルールが期待通りプロキシされること(Workers 実行ログで確認) - Analytics / Caching など Cloudflare 側設定が要件どおりになっていること
pnpm exec wrangler versions list --jsonで、想定したworkers/message/workers/tagを持つ version が upload 済みであることhttps://order.ritsubi-platform.com/auth/loginがHTTP 200を返し、Cloudflare 配下の Storefront HTML を返していること- ログイン経路は
just storefront-login-smoke-production-domainsでscripts/ops/deploy-targets.shの canonical URL と public alias URL を すべて確認すること。order.ritsubi-platform.com単体の smoke では alias domain のOrigin/ CORS drift を検出できない。
6. 補足: Vite 正本の CF Workers build¶
Vite storefront の Cloudflare Workers build / deploy フローは
apps/storefront/project.json の Nx target を正本とします。
詳細は apps/storefront のプロジェクト設定を参照してください。