Xisound 前端构建与部署拓扑 v1.0
文档定位
- 上游:D3-FE-ARCH-001 顶层架构 §3 Monorepo 结构 · §6.4 构建与发布
- 本文范围:Monorepo 构建工具链 + CI/CD 流水线 + 6 apps 的部署拓扑 + 域名规划 + 环境变量管理
- 目标读者:DevOps 工程师 / 前端工程 Leader / SRE
- 约束强度:C-07(packages SemVer)· C-09(统一版本)· DQ-04(XiVST 域名与账号体系)· DQ-06(Monorepo 位置)
1. 构建工具链总览
1.1 技术栈
| 层 | 选型 | 角色 |
|---|---|---|
| 包管理 | pnpm 9+ | workspace + 高效硬链接 + 严格依赖 |
| 构建编排 | Turborepo 2+ | 增量构建缓存 + 并行任务 + 远程缓存(可选) |
| app 构建 | Vite 5+ | 每个 app 独立 build |
| packages 构建 | tsup(基础 package) / Vite lib mode(@xi/ui-kit) | 产出 CommonJS + ESM + TypeScript 类型 |
| 版本管理 | changesets 2+ | 自动语义化版本 + CHANGELOG |
| Node 版本 | Node 20 LTS | .nvmrc 锁定 |
| 包管理器锁定 | packageManager in root package.json |
防止 npm/yarn 误用 |
1.2 pnpm-workspace.yaml
1.3 root package.json 关键字段
{
"name": "xi-platform",
"private": true,
"packageManager": "pnpm@9.0.0",
"engines": {
"node": ">=20.0.0",
"pnpm": ">=9.0.0"
},
"scripts": {
"dev": "turbo run dev --parallel",
"build": "turbo run build",
"lint": "turbo run lint",
"test": "turbo run test",
"type-check": "turbo run type-check",
"changeset": "changeset",
"version-packages": "changeset version",
"release": "turbo run build --filter='./packages/*' && changeset publish"
},
"devDependencies": {
"turbo": "^2.0.0",
"@changesets/cli": "^2.27.0",
"typescript": "^5.3.0",
"vitest": "^1.6.0",
"@playwright/test": "^1.59.0"
}
}
1.4 turbo.json(构建编排)
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "build/**"],
"cache": true
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"outputs": []
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"cache": true
},
"type-check": {
"dependsOn": ["^build"],
"outputs": []
},
"e2e": {
"dependsOn": ["build"],
"outputs": ["playwright-report/**", "test-results/**"]
}
}
}
1.5 本地开发命令
# 全量依赖安装
pnpm install
# 启动 xi-studio(依赖 forge/vst 组件热更新 + 所有 @xi/* packages)
pnpm -F xi-studio dev
# 同时启动多个 app(并行)
pnpm -F xi-studio dev & pnpm -F xi-tune dev
# 仅 build 特定 app + 其依赖
pnpm -F xi-tune build
# 全部 build
pnpm build
# 跑 xi-studio 的 e2e
pnpm -F xi-studio e2e
# 跑所有 workspace 的单测
pnpm test
2. CI/CD 流水线
2.1 推荐平台
首选 GitHub Actions(Xisound 代码已在 GitHub),次选 Azure DevOps Pipelines(企业合规需要时)。
2.2 核心 Pipeline 阶段
graph LR
Push[Push/PR] --> Setup[setup node + pnpm]
Setup --> Cache[restore turbo cache]
Cache --> Install[pnpm install --frozen-lockfile]
Install --> Lint[pnpm lint]
Install --> TypeCheck[pnpm type-check]
Install --> UnitTest[pnpm test]
Lint --> BuildPkg[build packages]
TypeCheck --> BuildPkg
UnitTest --> BuildPkg
BuildPkg --> BuildApps[build changed apps]
BuildApps --> E2E[e2e tests]
E2E --> Deploy{branch?}
Deploy -->|main| Prod[Deploy to prod]
Deploy -->|staging| Staging[Deploy to staging]
Deploy -->|PR| Preview[Deploy preview]
2.3 GitHub Actions 样例(核心工作流)
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, staging]
pull_request:
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: xisound
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # Turborepo 需要 diff
- uses: pnpm/action-setup@v3
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm type-check
- run: pnpm test
- run: pnpm build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ github.sha }}
path: |
apps/*/dist
packages/*/dist
retention-days: 7
2.4 增量构建优化(Turborepo)
# Turbo 自动按 git diff 判断哪些 package/app 需要重建
# 未变更的 app 直接复用缓存(秒级 build)
# 示例:只改了 packages/ui-kit 的一个组件
# → Turbo 判定受影响的下游:xi-studio / xi-forge / xi-tune / xi-test / xi-probe
# → 其他仍未变更的 package 走缓存(build 命中 cache HIT)
# 启用远程缓存(Turbo 官方或自建 Redis):
# .turbo/config.json
{
"teamId": "xisound",
"remoteCache": { "enabled": true, "signature": true }
}
2.5 PR Preview 部署(Vercel 风格)
对每个 PR 自动部署 preview 环境:
xi-studioPR #42 →pr-42-xi-studio.xi-preview.xisound.comxi-tunePR #42 →pr-42-xi-tune.xi-preview.xisound.com
实现方式:Cloudflare Pages / Vercel / Netlify 都原生支持;自建可用 GitHub Actions + Nginx 动态子域名。
3. 部署拓扑
3.1 域名规划(权威 · 对齐 DQ-04)
| App | 生产域名 | Staging | 开发环境 |
|---|---|---|---|
| xi-studio | studio.xisound.com |
studio-staging.xisound.com |
localhost:5173 |
| xi-tune | tune.xisound.com |
tune-staging.xisound.com |
localhost:5175 |
| xi-test | test.xisound.com |
test-staging.xisound.com |
localhost:5176 |
| xi-probe | probe.xisound.com |
probe-staging.xisound.com |
localhost:5177 |
| xi-vst (Marketplace) | marketplace.xisound.com + xvst.dev(国际域名可选) |
marketplace-staging.xisound.com |
localhost:5178 |
| xi-vst (embedded) | 走 studio.xisound.com 子路径 /algo-library/xivst |
— | — |
| xi-forge | 无独立域名(内嵌 xi-studio 的 /forge 路由) | — | localhost:5174(独立 dev server 仅开发用) |
| docs (MkDocs) | docs.xisound.com(或 docs.joysnd.com · 当前规划) |
— | — |
| 品牌站 | xisound.com |
— | — |
| 开发者文档 | dev.xisound.com / xvst.dev/docs |
— | — |
3.2 统一 SSO 与 Cookie 策略(DQ-05)
graph TB
SSO[auth.xisound.com<br/>统一登录]
SSO -.cookie: .xisound.com.-> Studio[studio.xisound.com]
SSO -.cookie: .xisound.com.-> Tune[tune.xisound.com]
SSO -.cookie: .xisound.com.-> Test[test.xisound.com]
SSO -.cookie: .xisound.com.-> Probe[probe.xisound.com]
SSO -.cookie: .xisound.com.-> MP[marketplace.xisound.com]
class SSO xyL3
约定:
- SSO Cookie
Domain=.xisound.com(跨所有子域名共享) HttpOnly + Secure + SameSite=Lax默认- Tool Token(deep-link 用)走 URL 参数 · 不用 Cookie(防止 CSRF)
- 国际域名(xvst.dev)需要独立 SSO 或 OAuth 集成
3.3 部署架构(Cloudflare Pages + 自建 Backend 方案)
graph TB
subgraph EdgeCDN["Cloudflare Edge (CDN + DDoS + TLS)"]
CDN[静态资源 CDN<br/>JS/CSS/Images]
WAF[WAF + Rate Limit]
end
subgraph FrontendHost["Cloudflare Pages / Netlify"]
Studio[studio.xisound.com]
Tune[tune.xisound.com]
Test[test.xisound.com]
Probe[probe.xisound.com]
MP[marketplace.xisound.com]
end
subgraph BackendVPS["VPS / Azure / AliCloud"]
API[api.xisound.com<br/>C# ASP.NET Core]
WS[ws.xisound.com<br/>WebSocket 服务]
AuthSvc[auth.xisound.com<br/>认证服务]
AISvc[ai.xisound.com<br/>XiMind 后端]
end
subgraph Storage["对象存储"]
S3[xisound-assets<br/>S3/OSS/COS<br/>presets/wav/reports]
AlgoRepo[xisound-algo-repo<br/>私有算法仓库]
end
User[用户浏览器] --> CDN
CDN --> FrontendHost
FrontendHost -.API calls.-> API
FrontendHost -.WebSocket.-> WS
FrontendHost -.Login.-> AuthSvc
FrontendHost -.Copilot.-> AISvc
API --> S3
API --> AlgoRepo
class CDN,WAF xyL3
class Studio,Tune,Test,Probe,MP xyL2
class API,WS,AuthSvc,AISvc xyL4
class S3,AlgoRepo xyL0
class EdgeCDN xySgL0; class FrontendHost xySgL4; class BackendVPS xySgL3; class Storage xySgL1;
3.4 Nginx/Cloudflare 配置要点
SPA fallback(必需)
# /etc/nginx/sites-available/studio.xisound.com
server {
server_name studio.xisound.com;
root /var/www/xi-studio/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html; # SPA fallback · history mode 路由必需
}
# 静态资源长缓存(hash in filename)
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# index.html 不缓存
location = /index.html {
add_header Cache-Control "no-cache";
}
# API 反向代理(同域名避免 CORS)
location /api/ {
proxy_pass https://api.xisound.com/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# WebSocket 反向代理
location /ws/ {
proxy_pass https://ws.xisound.com/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
}
Cloudflare Page Rules(如果用 CF Pages)
studio.xisound.com/assets/*→ Cache Level: Cache Everything · Edge TTL: 1 yearstudio.xisound.com/*→ Cache Level: Bypass(动态内容)*.xisound.com/api/*→ Cache Level: Bypass
3.5 XiVST Marketplace 特殊说明(SEO 需求)
问题:SPA 默认对 SEO 不友好(搜索引擎抓取到空 HTML)
方案:
- Y1 方案:用
vite-ssg(静态预渲染)生成 Marketplace 页面的 HTML 快照 - Y2 方案:如流量大且需动态 SEO,改用 Nuxt 3 做 SSR
- Dev Docs(
xvst.dev/docs):用 MkDocs Material 或 VitePress 静态生成
实现要点(vite-ssg):
// apps/xi-vst/marketplace/vite.config.ts
import { defineConfig } from 'vite'
import { ViteSSG } from 'vite-ssg/plugin'
export default defineConfig({
plugins: [ViteSSG({
includedRoutes: (paths, routes) => {
// 预渲染路由列表(landing + 热门 plugin 详情)
return [...paths, ...topPlugins.map(p => `/plugin/${p.slug}`)]
}
})]
})
4. 环境变量与密钥管理
4.1 分层
xi-platform/
├── .env # 不提交 · 本地兜底
├── .env.example # 提交 · 示例值
├── apps/
│ ├── xi-studio/
│ │ ├── .env.development # 开发环境默认
│ │ ├── .env.staging # Staging
│ │ └── .env.production # 生产(CI 注入 · 不提交真实值)
4.2 变量命名规范
| 前缀 | 用途 |
|---|---|
VITE_XI_API_BASE |
后端 API 地址(浏览器可见) |
VITE_XI_WS_URL |
WebSocket 地址 |
VITE_XI_SSO_URL |
SSO 服务地址 |
VITE_XI_AI_ENDPOINT |
XiMind 后端 |
VITE_XI_SENTRY_DSN |
Sentry 错误上报(可选) |
VITE_XI_FEATURE_FLAGS |
Feature toggle JSON |
关键约束:
- 所有浏览器运行时变量必须以
VITE_开头(Vite 要求) - 密钥(API Key / JWT Secret / Sentry Auth Token)必须在 CI 注入,禁止写入 repo
- 使用 GitHub Secrets / Azure Key Vault / HashiCorp Vault 管理
4.3 密钥清单
| 密钥 | 存放位置 | 使用方 |
|---|---|---|
SSO_JWT_SECRET |
Backend Vault | 后端签发 JWT |
XIMIND_API_KEY |
Backend Vault | 后端调用 AI 上游 |
CLOUDFLARE_API_TOKEN |
GitHub Secrets | CI 部署 |
TURBO_TOKEN |
GitHub Secrets | Turborepo 远程缓存 |
SENTRY_AUTH_TOKEN |
GitHub Secrets | 上传 sourcemap |
NPM_REGISTRY_TOKEN |
GitHub Secrets | 私有 packages 发布(Y2+) |
5. 版本发布流程
5.1 Packages 版本(@xi/* 内部库)
# 开发者修改 package 后
pnpm changeset
# → 交互式选择受影响 packages + 语义版本(major/minor/patch)+ 填写变更描述
# 提交 changeset 文件到 PR(不直接改版本号)
git add .changeset/*.md && git commit
# merge 到 main 后 CI 自动执行:
pnpm changeset version # 根据积累的 changeset 汇总计算新版本 + 生成 CHANGELOG
pnpm build --filter='./packages/*'
pnpm changeset publish # 发布到私有 npm(Y2+) 或仅本地滚动(Y1)
5.2 Apps 版本
- 不发布到 npm(都是最终应用)
- 每次 main 分支合并触发 CI 自动部署到 staging
- 手动 tag
v{app}-{version}触发 prod 部署(如v-xi-studio-1.0.0)
5.3 Apps 独立发布节奏
| 约束 | 说明 |
|---|---|
| 独立版本号 | 每个 app 维护独立 SemVer · xi-studio@1.0.0 与 xi-tune@0.9.0 解耦 |
| packages 通过 workspace:* 引用 | app build 时会固化到具体版本 |
| 跨 app 破坏性变更 | 如 @xi/protocol 发 major 版本 · 所有依赖 app 同批次升级 |
| 回滚 | 每次 prod 部署生成不可变 snapshot · 支持秒级回滚 |
6. 监控与可观测
6.1 错误追踪(Sentry)
// apps/xi-studio/src/main.ts
import * as Sentry from '@sentry/vue'
import { app } from './App.vue'
if (import.meta.env.PROD) {
Sentry.init({
app,
dsn: import.meta.env.VITE_XI_SENTRY_DSN,
environment: import.meta.env.MODE,
release: `xi-studio@${__APP_VERSION__}`,
integrations: [new Sentry.BrowserTracing()],
tracesSampleRate: 0.1, // 采样率
})
}
6.2 前端性能指标(Web Vitals)
上报到后端 /api/telemetry/vitals(聚合到 Prometheus/Grafana):
- LCP(Largest Contentful Paint)< 2.5s
- FID(First Input Delay)< 100ms
- CLS(Cumulative Layout Shift)< 0.1
- 自定义业务指标:LinkEditor 打开时间 / Signal Flow 渲染帧率 / Copilot 首字节
6.3 日志策略
- 浏览器端仅
console.error上报到 Sentry - 避免
console.log在生产暴露敏感信息(PII) - CI 阶段用 ESLint 规则
no-console限制(仅允许 warn/error)
7. DQ 清单
| DQ 编号 | 问题 | 建议 |
|---|---|---|
| DQ-DEPLOY-01 | 是否全部走 Cloudflare Pages,还是自建 Nginx + VPS | 前端用 CF Pages(免运维)· 后端 API/WS 自建 VPS(已 M6.2 完成) |
| DQ-DEPLOY-02 | 海外用户加速(EMEA/US) | CF CDN 天然覆盖 · 无需额外部署 |
| DQ-DEPLOY-03 | 私有化部署包(Tier1 IT 合规要求) | Y2 提供 Docker Compose 全栈镜像 · 文档单独出 |
| DQ-DEPLOY-04 | Tauri 桌面版的分发(XiProbe Y2) | macOS 走 DMG + 自家签名 · Windows 走 MSIX + 代码签名 · 更新走 Tauri updater |
| DQ-DEPLOY-05 | changesets 自动 release 是否启用 GitHub Action changesets/action |
推荐启用 · 免手动 tag |
8. 版本与变更记录
| 版本 | 日期 | 作者 | 说明 |
|---|---|---|---|
| v1.0 | 2026-05-08 | work-cline | 初稿 · Monorepo 构建工具链 + CI/CD + 部署拓扑 + 域名规划 + 环境变量 + 监控 |
附录 A · 引用
- D3-FE-ARCH-001 顶层架构(§3.2 Monorepo 目录结构 · §6.4 构建发布)
- D3-FE-ARCH-005 路由与 Deep-link(§3.5 XiVST Marketplace SEO)
- D3-architecture/deployment-topology/(后端 VPS 部署 M6.2 文档)
- docs-site-deployment.md(MkDocs 站点部署)