# Taro H5 三入口部署说明 更新时间:2026-07-01 当前 `apps/taro` 采用一个 Taro 4 React 工程、三套 H5 产物的方式交付: - 学生学习端:刷题、背单词、知识手册、分数线、资料、会员、个人中心。 - 租户后台:品牌、主题、域名、题库、导入、学生、订单、营销、销售、CRM、财务和数据看板。 - 平台后台:租户、SaaS 套餐、订阅账单、公共题库授权和平台审计。 后续微信小程序仍复用同一套业务 services 和页面逻辑,但 H5 是当前优先上线形态。 ## 构建命令 ```bash npm run build:taro:h5:student npm run build:taro:h5:tenant npm run build:taro:h5:platform ``` 输出目录: ```text apps/taro/dist/h5-student apps/taro/dist/h5-tenant-admin apps/taro/dist/h5-platform-admin ``` 注意:Taro H5 入口依赖 `apps/taro/src/index.html` 模板生成 `index.html`。如果构建产物目录里只有 `js/css/assets` 而没有 `index.html`,不要发布;重新构建并运行发布守卫脚本。 推荐部署: | 域名 | 静态目录 | 说明 | | --- | --- | --- | | `www.example.com` 或租户自有学生端域名 | `h5-student` | 面向学生和 C 端用户 | | `admin.example.com` | `h5-tenant-admin` | 面向租户公司运营、教师、销售、代理、管理员 | | `console.example.com` | `h5-platform-admin` | 面向平台超级管理员 | 三个入口可以放在同一台服务器的三个静态目录,也可以分别放到不同服务器或 CDN/对象存储静态网站。API 推荐独立域名,例如 `api.example.com`。 ## 运行时配置 H5 产物支持运行时覆盖公开配置。每个静态目录根部放一个 `runtime-config.json`: ```text /www/tiku/h5-student/runtime-config.json /www/tiku/h5-tenant-admin/runtime-config.json /www/tiku/h5-platform-admin/runtime-config.json ``` 示例文件: ```text apps/taro/deploy/h5-student.runtime-config.example.json apps/taro/deploy/h5-tenant-admin.runtime-config.example.json apps/taro/deploy/h5-platform-admin.runtime-config.example.json ``` 生产示例: ```json { "portal": "student", "apiBaseUrl": "https://api.example.com", "supabaseUrl": "https://auth.example.com", "supabasePublishableKey": "replace-with-supabase-publishable-key", "tenantCode": "" } ``` 允许字段: ```text portal student | tenant-admin | platform-admin apiBaseUrl apps/api 公开 HTTPS 地址 supabaseUrl Supabase Auth/API 公开 HTTPS 地址 supabasePublishableKey Supabase publishable/anon key tenantCode 小程序、预览环境或指定租户部署可用 ``` 这些字段是前端公开配置,不是密钥。`apps/taro/src/env.ts` 会拒绝 `runtime-config.json` 中出现服务端密钥类字段,例如: ```text SUPABASE_SERVICE_ROLE_KEY SUPABASE_SECRET_KEY DATABASE_URL ALIYUN_OSS_ACCESS_KEY_SECRET TENCENT_COS_SECRET_KEY WECHAT_PAY_PRIVATE_KEY ALIPAY_APP_PRIVATE_KEY AUTH_SESSION_SECRET PLATFORM_ADMIN_API_KEY ``` 构建时仍可以设置同名 `TARO_APP_*` 变量作为默认值,但生产更推荐用 `runtime-config.json`。这样 API 域名、Auth 域名、租户预览码变化时不需要重新构建 H5。 ## Nginx 示例 H5 使用 browser history 路由时,静态服务器需要把未知路径回退到 `index.html`。同时对 `runtime-config.json` 禁用缓存,对 hash 后的 JS/CSS 长缓存。 ```nginx server { listen 443 ssl http2; server_name www.example.com; root /www/tiku/h5-student; add_header X-Content-Type-Options nosniff always; add_header Referrer-Policy strict-origin-when-cross-origin always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https: blob:; font-src 'self' data:; connect-src 'self' https://api.example.com https://auth.example.com; media-src 'self' https: blob:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always; location = /runtime-config.json { add_header Cache-Control "no-store" always; try_files $uri =404; } location ~* \.(?:js|css|woff2?|png|jpg|jpeg|gif|svg)$ { add_header Cache-Control "public, max-age=31536000, immutable" always; try_files $uri =404; } location / { try_files $uri $uri/ /index.html; } } ``` 租户后台和平台后台复用同样规则,替换 `server_name`、`root` 和 CSP 中的 `connect-src` 域名即可。若学生端需要打开 OSS/COS/CDN 签名资源,`img-src/media-src` 可加入对应 HTTPS 域名;不要加入通配符 `*`。 ## CORS 和 Cookie API 的生产 `CORS_ORIGIN` 必须只包含实际前端域名: ```text CORS_ORIGIN=https://www.example.com,https://admin.example.com,https://console.example.com ``` 禁止生产环境使用: ```text CORS_ORIGIN=* ``` 当前前端以 `Authorization: Bearer ` 调用 API,`x-tenant-id` 只作为租户上下文,不作为身份来源。生产建议: ```text ALLOW_LEGACY_AUTH_HEADERS=false ALLOW_PLATFORM_ADMIN_KEY=false ``` H5 正式回归时建议把前端登录态切到 Supabase Auth,并观察业务接口请求是否都发送 `Bearer `。`tk_` session 只作为迁移/本地兜底,不应成为线上长期依赖。 ## 前端请求边界 - 所有页面统一通过 `apps/taro/src/services/api.ts` 调用后端。 - 默认请求模式是 `authMode='auto'`:H5 先用 Supabase JWT,没有 JWT 才兜底迁移期 `tk_` session。 - 公共接口、短信登录、租户解析必须显式 `authMode='none'`;平台全局或租户解析不应带租户上下文时必须显式 `tenantId: null`。 - H5 可以用 Supabase client 管理 Auth session/JWT,但业务数据默认走 `apps/api`。 - 页面代码不能通过 `headers` 覆盖 `Authorization` 或 `x-tenant-id`,身份和租户上下文只能走统一 client 的 token provider、`authMode` 和 `tenantId` 参数。 - 订单、支付、权益、内容导入、后台配置、CRM、对象存储签名、视频播放签名必须走后端命令层。 - 登录后禁止传 `x-user-id` 或 body/query `userId` 表示当前用户。 - 私有 PDF、图片、视频不能由前端拼接 URL,必须使用 `content_assets` 和后端短签名。 ## 发布步骤 1. 在新服务器或 CI 环境构建三套 H5: ```bash npm ci npm run build:taro:h5:student npm run build:taro:h5:tenant npm run build:taro:h5:platform ``` 2. 拷贝静态产物到对应 Web 根目录。 3. 根据示例文件创建每个目录的 `runtime-config.json`。 4. 配置 Nginx history fallback、缓存策略、安全响应头和 HTTPS。 5. 配置 API 的 `CORS_ORIGIN`、Supabase Auth 回调域名、微信/QQ/支付宝/微信支付回调域名。 6. 运行生产就绪检查: ```bash npm run readiness:production npm run readiness:production:db npm run check:taro ``` 构建后再运行 H5 发布守卫脚本: ```bash npm run smoke:taro:h5 npm run smoke:taro:h5:interaction npm run manifest:taro:h5 node scripts/taro-h5-release-guardrails-test.js --require-dist ``` `smoke:taro:h5` 会用临时静态服务器检查三套 H5 产物可托管、资源可加载、history fallback 可用,并用 mock API 验证租户解析契约。`smoke:taro:h5:interaction` 会用真实 Chrome/Edge 打开三套发布产物并点击学生刷题/收藏/会员、租户题库内容/财务、平台租户/账务中心关键路径;若服务器没有默认浏览器,可设置 `TARO_H5_SMOKE_BROWSER=/path/to/chrome`。`manifest:taro:h5` 会生成三套 H5 的部署清单,包含构建命令、发布目录、入口路由、`index.html` hash、资源数量、runtime-config 是否存在、租户解析模式和公开配置状态。发布守卫会检查三套 H5 产物是否存在 `index.html`,源码和产物是否混入 `x-user-id`、`x-platform-admin-key`、PocketBase 引用、数据库连接串、服务端密钥形态,并检查运行时配置示例只包含公开字段。若还没有把真实 `runtime-config.json` 放入静态目录,会显示 warning;正式发布前必须在每个 H5 目录根部补齐该文件。 写入 `production-launch-evidence.json` 的正式证据必须使用严格模式,确保三套发布目录都已放置真实公开 `runtime-config.json` 且没有 warning: ```bash npm --silent run smoke:taro:h5 -- --json > docs/refactor/launch-artifacts/taro-h5-static-smoke.json npm --silent run smoke:taro:h5:interaction -- --json > docs/refactor/launch-artifacts/taro-h5-interaction-smoke.json node scripts/taro-h5-release-guardrails-test.js --require-dist --require-runtime-config --json > docs/refactor/launch-artifacts/taro-h5-release-guardrails.json npm --silent run manifest:taro:h5 -- --require-dist --require-runtime-config --json --write docs/refactor/launch-artifacts/taro-h5-release-manifest.json > docs/refactor/launch-artifacts/taro-h5-release-manifest.stdout.json ``` 7. 收集生产上线证据并运行 launch gate: ```bash cp docs/refactor/production-launch-evidence.template.json docs/refactor/production-launch-evidence.json npm run launch:gate -- --evidence docs/refactor/production-launch-evidence.json ``` 证据文件只保存命令摘要、artifact 路径、审批人和时间,不保存真实 access token、支付密钥、对象存储密钥或用户隐私明细。真实 artifact 建议放在 `docs/refactor/launch-artifacts/`,该目录不入 Git。 8. 打开三个域名,确认 `index.html` 正常加载,启动页能解析租户,登录后接口请求使用 `Authorization` 和正确的 `x-tenant-id`。 ## 安全审计边界 H5 线上只发布 `apps/taro/dist/**` 静态文件和每个目录自己的 `runtime-config.json`,不要把 `apps/taro/node_modules`、源码目录、`.env`、部署脚本缓存放进 Web 根目录。 后端/API/worker 的生产依赖审计使用: ```bash npm run audit:runtime ``` Taro 4.2.0 当前构建工具链仍可能触发 `npm run audit:taro:toolchain` 的上游 high/critical 告警,主要来自构建期 CLI、webpack、swiper、lodash-es 等传递依赖。不要使用 `npm audit fix --force` 将 Taro 降级到 3.x;应等 Taro 官方升级后再处理,或后续评估 Vite runner 替代方案。上线时以静态产物、前端密钥检查、CORS 域名白名单、CSP 和 API runtime audit 作为阻断项。 ## 小程序后续兼容 当前 `runtime-config.json` 只用于 H5。微信小程序版本应通过编译变量、小程序启动参数或后台小程序配置传入 `tenantCode`,再调用 `GET /api/tenant/resolve?tenantCode=...`。小程序端如 `supabase-js` 兼容性不稳定,保留 `apps/api/auth/*` 登录适配层,H5 继续使用 Supabase client 管理 Auth。