跳转到内容

部署到 Cloudflare Pages

每家店铺是一个独立的 Cloudflare Pages 项目。构建通过 PUBLIC_* 环境变量注入品牌信息,因此同一次提交只需改变环境即可部署到任意 店铺。

Terminal window
npm install
PUBLIC_BRAND_SLUG=store-b \
PUBLIC_BRAND_NAME='Store B' \
PUBLIC_BRAND_LOGO=/images/store-b-logo.png \
PUBLIC_BRAND_PRIMARY='#0F766E' \
PUBLIC_BRAND_MENU='gear:Gear,apparel:Apparel' \
PUBLIC_API_BASE=https://api.store-b.example.com/api/v1 \
RCOMMERCE_API_URL=https://api.store-b.example.com \
PUBLIC_AIRWALLEX_ENV=demo \
PUBLIC_HERO_VIDEO_URL='https://customer-<id>.cloudflarestream.com/<video-id>/iframe?muted=true&preload=true&loop=true&autoplay=true&controls=false' \
npm run build

所有 PUBLIC_* 值都在构建时内联——只在 Pages 面板设置而构建环境 没有它们是不生效的。最稳妥的做法:把整套值放进按品牌的 wrangler.<brand>.toml(见下文),并用同样的值构建。

Terminal window
npx wrangler pages deploy dist --project-name=<project> --branch=main

把店铺域名绑定到项目(Pages → Settings → Domains),例如 my-storefront 绑定 store-a.example.com + www.store-a.example.com, store-b-pages 绑定 store-b.example.com。

storefront/wrangler.store-b.toml 是参考示例——按店铺复制并修改:

# 店铺B 店面 —— 以 店铺B 品牌和 store-b 后端部署到 store-b-pages Pages 项目。
# 先用同样的 PUBLIC_* 值执行构建(它们在构建时内联):
#
# PUBLIC_BRAND_SLUG=store-b PUBLIC_BRAND_NAME='Store B' \
# PUBLIC_BRAND_LOGO=/images/store-b-logo.png PUBLIC_BRAND_PRIMARY=#0F766E \
# PUBLIC_BRAND_MENU='gear:Gear,apparel:Apparel' \
# PUBLIC_API_BASE=https://api.store-b.example.com/api/v1 \
# RCOMMERCE_API_URL=https://api.store-b.example.com \
# PUBLIC_AIRWALLEX_ENV=demo \
# PUBLIC_HERO_VIDEO_URL='https://…' \
# npm run build
# npx wrangler pages deploy dist --config wrangler.store-b.toml --branch=main
name = "store-b-pages"
pages_build_output_dir = "dist"
compatibility_date = "2025-06-01"
compatibility_flags = ["nodejs_compat"]
[vars]
PUBLIC_AIRWALLEX_ENV = "demo"
PUBLIC_API_BASE = "https://api.store-b.example.com/api/v1"
RCOMMERCE_API_URL = "https://api.store-b.example.com"
PUBLIC_BRAND_SLUG = "store-b"
PUBLIC_BRAND_NAME = "Store B"
PUBLIC_BRAND_LOGO = "/images/store-b-logo.png"
PUBLIC_BRAND_PRIMARY = "#0F766E"
PUBLIC_HERO_VIDEO_URL = "https://customer-<id>.cloudflarestream.com/<video-id>/iframe?muted=true&preload=true&loop=true&autoplay=true&controls=false"
PUBLIC_BRAND_MENU = "gear:Gear,apparel:Apparel"

有两项要求容易被忽略:

  • compatibility_date = "2025-06-01" —— 店面依赖该日期起的 Pages 运行时行为,不要让面板自动向前滚动。
  • compatibility_flags = ["nodejs_compat"] —— Astro SSR 输出和 API 代理函数都需要它。

在项目的 production 环境中设置以下变量(它们作用于运行时 代理,而非构建):

变量示例
RCOMMERCE_API_URLhttps://api.store-b.example.com
PUBLIC_API_BASEhttps://api.store-b.example.com/api/v1
PUBLIC_AIRWALLEX_ENVdemo 或 prod
PUBLIC_BRAND_SLUGstore-b
PUBLIC_BRAND_NAMEStore B
PUBLIC_BRAND_LOGO/images/store-b-logo.png
PUBLIC_BRAND_PRIMARY#0F766E
PUBLIC_BRAND_MENUgear:Gear,apparel:Apparel
PUBLIC_HERO_VIDEO_URLCloudflare Stream iframe URL

Airwallex 的构建时值只是兜底:运行时时后端结账 summary 中的 airwallex_env 始终优先。

Pages 保留每一次部署;可在面板中回滚(Deployments → ⋮ → Rollback), 或重新部署之前的 production 部署。