コンテンツにスキップ

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: ASSETS binding で静的配信を行い、/assets/*favicon.ico のような ファイルリクエストはそのまま返し、その他は SPA fallback として / を返す。 過去の OpenNext 運用で作成された Durable Object class (DOShardedTagCache / DOQueueHandler / BucketCachePurge) は Cloudflare 側の worker metadata に残るため、Vite 移行後も worker.js では互換 stub export を維持する。これを消すと wrangler versions uploadcode: 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_KV binding を正本にする: 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.mjsCLOUDFLARE_MAINTENANCE_KV_NAMESPACE_ID を一時 Wrangler config へ注入し、 wrangler versions uploadwrangler versions view で binding 検証 → wrangler versions deploy の順で反映する。

現在の Storefront Worker は wrangler.tomlsecrets.required を使っていない。 experimental warning を避けるため、runtime secret の存在確認は deploy 時の with-cloudflare-auth.sh / cloudflare-deploy.mjs と環境側の secret 正本で担保する。

wrangler.toml では MAINTENANCE_KV placeholder を production は top-level table 群の前、 staging / preview / mock は各 [env.<target>] の前に置き、生成される binding が 期待どおりの TOML scope に入るようにする。

既存 Worker が過去の Durable Object class を保持している環境では、 wrangler versions uploadNew 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_KV binding は apps/storefront/scripts/cloudflare-deploy.mjs が target 環境の CLOUDFLARE_MAINTENANCE_KV_NAMESPACE_ID から生成し、未設定なら deploy を失敗させる。
  • deploy script は upload 後に wrangler versions viewMAINTENANCE_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 環境の *_shared secret に設定し、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_ID
  • CLOUDFLARE_MAINTENANCE_KV_NAMESPACE_ID
  • CLOUDFLARE_API_TOKEN

CLOUDFLARE_API_TOKEN は対象 namespace の read / write のみ許可する最小権限トークンに限定する。

3.2 WordPress アセット配信(Cloudflare)

WordPress 本文内の wp-content/uploads を高速配信するため、アセット専用サブドメインを Cloudflare 配下に置く。

  1. DNS
  2. cms-assets.<domain> を WordPress media 用 R2 配信先へ CNAME
  3. proxied=true(オレンジクラウド)で有効化
  4. Cloudflare Cache Rules
  5. 対象: cms-assets.<domain>/wp-content/uploads/*
  6. キャッシュTTLを長めに設定(更新頻度に応じて数日〜数週間)
  7. Storefront 環境変数
  8. storefront secret に VITE_PUBLIC_WORDPRESS_ASSET_BASE_URL=https://cms-assets.<domain>
  9. shared secret の VITE_PUBLIC_ASSET_HOSTScms-assets.<domain> を追加
  10. VITE_PUBLIC_ASSET_HOSTSec-assets.<domain>,cms-assets.<domain> のように両方を持たせる
  11. Storefront deploy
  12. secret 更新後に just cloudflare-deploy-storefront production production_storefront または just deploy-storefront-staging staging_storefront を実行
  13. VITE_PUBLIC_ASSET_HOSTSstorefront 側へ重複定義すると deploy 時に duplicate key error になるため、正本は shared に統一する

WordPress 側の offload 設定、既存メディア移行、R2 検証は wordpress-media-offload.md を参照してください。

3.2.1 Vendure アセット配信(Cloudflare)

商品画像を API ドメインと分離する場合は、Vendure の public asset URL を専用サブドメインへ向ける。

  1. DNS
  2. ec-assets.<domain> を Vendure asset 配信先へ向ける
  3. Storefront / Vendure 環境変数
  4. VENDURE_ASSET_URL=https://ec-assets.<domain>
  5. 運用原則
  6. Storefront の commerce API は VENDURE_BASE_URL
  7. 商品画像だけ VENDURE_ASSET_URL
  8. 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.txtDisallow: / を返す

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 を temporary wrangler.toml へ注入する
  • production は [[kv_namespaces]]、staging / preview / mock は [[env.<target>.kv_namespaces]] を使って binding の scope を合わせる
  • wrangler versions upload で新しい Worker version を作成する
  • wrangler versions view で upload 済み version に MAINTENANCE_KV binding があることを検証する
  • 検証済み 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.yaml
  • pnpm-workspace.yaml
  • nx.json

ローカル(手動)

  1. 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 は bare wrangler 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 内の writable XDG_CONFIG_HOME に対する wrangler login / wrangler whoami によるユーザー認証を正とし、deploy 用 token 注入に寄せない
  • 手元確認の基本導線は、事前に同じ XDG_CONFIG_HOME で認証済みであることを前提に just cloudflare-whoamijust cloudflare-versions production の順とする
  • just cloudflare-deploy-storefront <env> / just cloudflare-verify-storefront <env> token / just cloudflare-deployments-status <env> が Cloudflare API Authentication 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_dispatchproduction / 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_KV binding を検証し、欠けている version の promote を拒否する

注意: wrangler secret bulk と Gradual Deployments の副作用

Cloudflare Workers が Gradual Deployments モードの場合、wrangler secret bulk を実行すると 暗黙的に新しい Worker version が作成される。この version には cloudflare-deploy.mjs の TOML 注入が適用されないため MAINTENANCE_KV binding が欠けた状態になり、 workers-version-deploy.yml の binding チェックで拒否される。

このため、production 環境の通常デプロイフローでは wrangler secret bulk を実行しない。 secrets は Prepare Production Storefront Version workflow で 込みのバージョンとしてビルド・事前 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 を参照する。

  1. デプロイ後に確認すべきポイント

  2. /commerce/* リライトルールが期待通りプロキシされること(Workers 実行ログで確認)

  3. Analytics / Caching など Cloudflare 側設定が要件どおりになっていること
  4. pnpm exec wrangler versions list --json で、想定した workers/message / workers/tag を持つ version が upload 済みであること
  5. https://order.ritsubi-platform.com/auth/loginHTTP 200 を返し、Cloudflare 配下の Storefront HTML を返していること
  6. ログイン経路は just storefront-login-smoke-production-domainsscripts/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 のプロジェクト設定を参照してください。