部署
AISCouncil 作为静态文件部署在 Cloudflare Pages 上,API 逻辑运行在 Cloudflare Workers 上。统一的部署脚本处理所有目标。
部署目标
| 目标 | URL | 类型 | 命令 |
|---|---|---|---|
| 应用 | aiscouncil.net | CF Pages(静态) | scripts/deploy.sh pages |
| 预发布 | aiscouncil.net | CF Pages(静态) | scripts/deploy.sh pages-staging |
| API Worker | api.aiscouncil.net | CF Worker | scripts/deploy.sh worker |
| 身份验证 Worker | auth.aiscouncil.net | CF Worker | scripts/deploy.sh worker-auth |
| 应用商店 | store.aiscouncil.net | CF Pages(静态) | scripts/deploy.sh store |
| 全部 | 以上所有 | 所有 | scripts/deploy.sh all |
环境变量
在 ~/.bashrc 中导出这些(永远不要提交它们):
export CF_ACCOUNT_ID_AISCOUNCIL="your-cloudflare-account-id"
export CF_PAGES_TOKEN_AISCOUNCIL="your-pages-api-token"
export CF_WORKER_TOKEN_AISCOUNCIL="your-worker-api-token"
可选覆盖:
export CF_PAGES_PROJECT_AISCOUNCIL="aiscouncil" # 默认
export CF_PAGES_PROJECT_AISCOUNCIL_STAGING="aiscouncil-staging" # 默认
这些令牌授予对您 Cloudflare 账户的部署访问权限。永远不要将它们提交到仓库。如果缺少必需变量,部署脚本将退出并显示错误。
Pages 部署(生产)
分步
- 从源代码组装应用程序:
./build.sh
- 部署到生产环境:
scripts/deploy.sh pages
此命令:
- 创建干净的
_deploy/目录 - 通过
rsync复制静态文件,排除开发产物 - 使用
html-minifier-terser压缩index.html(约 40% 大小减少) - 使用
--branch=main部署到 Cloudflare Pages - 清理
_deploy/
生产部署始终使用 --branch=main。这是 CF Pages 在生产域(aiscouncil.net)上提供服务所必需的。
部署什么
rsync 步骤排除所有不是面向浏览器的资产:
排除的目录: src/, tools/, kernel/, serve/, worker/, worker-auth/, doc.aiscouncil.net/, node_modules/, .git/, .github/, .carl/, .claude/, modules/, scripts/, core-types/, bridge/, i18n/, dist/, build/
排除的文件类型: *.py, *.zig, *.zon, *.md, *.sh, *.css, .env*
排除的配置文件: package.json, package-lock.json, vitest.config.*, tsconfig.json, .cfignore, .gitignore
剩下的是生产资产:index.html, sw.js, 图标, manifest.webmanifest, registry/ JSON 文件, sdk/, ads.json, sitemap.xml, 以及任何小程序或应用目录。
压缩
生产部署通过 html-minifier-terser 传递 index.html,使用这些选项:
- 折叠空白
- 删除注释
- 删除冗余属性
- 折叠布尔属性
- 压缩内联 CSS
- 压缩内联 JavaScript
典型大小减少约 40%(例如 980 KB 降至约 580 KB)。
预发布部署
无需压缩部署到预发布环境:
scripts/deploy.sh pages-staging
预发布从 aiscouncil.net 提供。应用程序在运行时自动检测其域,并相应调整 API URL、cookie 域和跨源引用。
将预发布提升为生产
在预发布上验证后,将相同的构建提升到生产:
scripts/deploy.sh promote
这将使用启用的压缩将当前代码重新部署到生产 Pages 项目。应用程序代码相同 —— 只有域更改。
Worker 部署
API Worker
scripts/deploy.sh worker
这使用您环境中的账户 ID 和 Worker 令牌在 worker/ 目录内运行 npx wrangler deploy。
身份验证 Worker
scripts/deploy.sh worker-auth
对于 worker-auth/ 目录的相同过程。
Worker 密钥
Worker 需要与代码部署分开设置的密钥。从 worker 目录使用 wrangler secret put:
cd worker
npx wrangler secret put JWT_SECRET
npx wrangler secret put STRIPE_SECRET_KEY
npx wrangler secret put STRIPE_WEBHOOK_SECRET
npx wrangler secret put WEBHOOK_PATH_SECRET
cd worker-auth
npx wrangler secret put JWT_SECRET
npx wrangler secret put GOOGLE_CLIENT_SECRET
npx wrangler secret put APPLE_CLIENT_SECRET
npx wrangler secret put GITHUB_CLIENT_SECRET
密钥在部署之间持久存在。您只需设置一次,或在轮换凭证时设置。
Worker 配置
每个 worker 都有一个 wrangler.toml,定义:
- Worker 名称和路由
- KV 命名空间绑定
- 环境变量引用
- 兼容性设置
Service Worker 缓存
客户端 Service Worker(sw.js)使用版本化缓存:
const CACHE = "ais-v1.0.0";
何时提升缓存版本:
- 应用程序 shell 的重大更改(HTML 结构、关键 CSS)
- 预缓存资产的更改(图标、清单)
- 主要版本发布
提升版本会导致 Service Worker:
- 使用新名称创建新缓存
- 预缓存所有列出的资产
- 激活时删除所有旧缓存
在重大更改后忘记提升缓存版本将导致用户看到过时内容,直到他们手动清除浏览器缓存或旧 Service Worker 过期。
部署所有内容
按顺序部署 Pages 应用程序、API worker 和身份验证 worker:
scripts/deploy.sh all
部署后验证
部署后,验证应用程序是否正确提供服务:
# 检查生产
curl -s https://aiscouncil.net/ | head -5
# 检查 API 健康状态
curl -s https://api.aiscouncil.net/health
# 检查身份验证健康状态
curl -s https://auth.aiscouncil.net/health
Cloudflare Pages 在部署时自动使其 CDN 缓存失效,但全球传播可能需要 1-2 分钟。如果您看到过时内容,请稍等片刻再试。
域架构
应用程序在运行时使用域检测来支持生产和预发布:
| 域 | 常量 | 生产 | 预发布 |
|---|---|---|---|
| 应用 | AIS.DOMAIN | aiscouncil.net | aiscouncil.net |
| 营销 | AIS.WWW | www.aiscouncil.net | www.aiscouncil.net |
| API | API_BASE | https://api.aiscouncil.net/v1 | https://api.aiscouncil.net/v1 |
| 身份验证 | AUTH_BASE | https://auth.aiscouncil.net/v1 | https://auth.aiscouncil.net/v1 |
| 文档 | AIS.DOC_BASE | https://doc.aiscouncil.net | https://doc.aiscouncil.net |
| 商店 | AIS.STORE_URL | https://store.aiscouncil.net | https://store.aiscouncil.net |
API 基础 URL 也可以通过 localStorage 为本地开发覆盖:
localStorage.setItem("ais-api-base", "http://localhost:8787/v1");
localStorage.setItem("ais-auth-base", "http://localhost:8788/v1");
本地开发
对于不部署的本地开发:
- 构建应用程序:
./build.sh - 使用任何静态文件服务器提供
index.html(例如python3 -m http.server 8080) - 使用 Wrangler 本地运行 Worker:
cd worker && npx wrangler dev
cd worker-auth && npx wrangler dev --port 8788
- 在浏览器控制台中覆盖 API 基础 URL:
localStorage.setItem("ais-api-base", "http://localhost:8787/v1");
localStorage.setItem("ais-auth-base", "http://localhost:8788/v1");
location.reload();