Appearance
第 4 步:构建、部署与验收
前提:前三章已经跑通真实请求、独立登录和订单保存返回。下面将基座和子应用部署到同一个 HTTPS 域名,统一 /api 网关,避免第一次上线同时引入跨源 Cookie 和跨源资源配置。
教学 API 只能用于本机验证。上线时由后端实现同样的协议或修改项目适配器,补齐真实用户、权限、订单资源归属、持久化、Secure Cookie 和 CSRF 校验。
1. 确定最终地址
| 用途 | 本章示例 |
|---|---|
| 基座 | https://portal.example.com/ |
| 子应用 HTML 入口 | https://portal.example.com/apps/order/ |
| 子应用独立入口 | https://portal.example.com/apps/order/#/home |
| API 网关 | https://portal.example.com/api/ |
example.com 地址需要替换为自己已配置 DNS 与证书的域名。entry 配置到子应用 HTML 所在目录,不带 #/list 或 /detail。
2. 配置生产变量
my-host/.env.production:
dotenv
VITE_AUTH_DEMO=false
VITE_MICRO_APP_ID=order
VITE_MICRO_APP_ENTRY=https://portal.example.com/apps/order/
VITE_API_BASE=/api/
VITE_TRUSTED_API_BASE=/api/
VITE_API_CREDENTIALS=trueorder-app/.env.production:
dotenv
VITE_MICRO_AUTH_MODE=auto
VITE_API_BASE=/api/
VITE_TRUSTED_API_BASE=/api/
VITE_API_CREDENTIALS=trueVite 的生产模式会使用这些配置;显式导出的进程环境变量优先级更高,CI 中也要检查。VITE_* 在构建时写入浏览器产物,改配置后必须重新构建,不能把 Token、密码或固定 CSRF 值放进去。
基座仍使用第二章的 platformSecurity.ts,从服务端读取 CSRF;生产缺值拒绝发送登录/注销请求。子应用独立认证和订单写接口也必须保留其 CSRF 接线。
3. 配置子应用静态资源 base
将 order-app/vite.config.ts 改为以下结构,开发仍使用根目录,构建时使用部署子目录:
ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig(({ command }) => ({
base: command === 'build' ? '/apps/order/' : '/',
plugins: [vue()],
server: {
port: 7101,
strictPort: true,
cors: { origin: ['http://localhost:7100', 'http://localhost:7101'], credentials: true },
proxy: { '/api': { target: 'http://127.0.0.1:7200', changeOrigin: true } },
},
}))基座部署在根目录,base 保持默认。子应用使用 hash 路由,嵌入时使用 memory history;不要为修复静态资源路径而改掉这些路由模式。
4. 分别检查和构建
在两个项目目录各执行:
sh
npm run check:runtime
npm run typecheck
npm run build每个项目都会生成自己的 dist。构建失败时先处理版本、类型和资源问题;vite preview 仅用于本地预览,不能替代生产服务器与 API 网关。
5. 部署目录与服务器示例
将两个 dist 的内容分别部署为:
text
/srv/fin/
├─ host/
│ ├─ index.html
│ └─ assets/
└─ apps/order/
├─ index.html
└─ assets/下面是 Nginx server 内的 location 示例;外层 HTTPS、证书、server_name 由实际部署配置提供,backend-service:8080 替换为真实后端。
nginx
root /srv/fin;
# /api 不得落入 SPA 的 index.html;后端收到原始 /api/... 路径。
location /api/ {
proxy_pass http://backend-service:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 子应用目录使用与 Vite base 一致的资源路径。
location ^~ /apps/order/ {
try_files $uri $uri/ /apps/order/index.html;
}
# 基座使用 history 路由,刷新 /home、/micro/order/detail 等地址须回到基座入口。
location / {
root /srv/fin/host;
try_files $uri $uri/ /index.html;
}这里两个前端同源,Wujie 资源无需额外跨源 CORS。未来拆成不同域名时,须分别配置子应用静态资源 CORS、API CORS、Cookie 策略和 CSP;开发服务器 cors/proxy 不会进入生产服务器。具体边界见平台适配与生产配置。
/micro/ 是基座的业务导航前缀,不能作为子应用静态资源部署目录;上述子应用资源使用 /apps/order/。宿主不再解析 /workspace?tab=...,旧书签需要改为 /micro/{appId}/{原业务路径}?query。
6. 上线前逐项验收
| 操作 | 应看到的结果 |
|---|---|
| 无痕打开基座 | 未登录先显示登录页,无工作区数据 |
| 真实账号登录 | 认证、menus、工作区按顺序就绪,无演示身份降级 |
| 从菜单打开订单列表 | 子应用 HTML、JS、CSS 200,业务接口获得合法身份 |
| 打开两个不同订单 | 独立页签、独立参数和草稿,同一订单不重复创建 |
| 保存备注 | 后端成功后才关闭详情,列表更新 |
| 刷新 /micro/order/detail?id=1001 | Nginx 返回基座 HTML,先恢复身份再恢复授权页签 |
| 独立打开子应用 | 无会话时登录,有会话时恢复;本地菜单可用 |
| 移除读取权限后重新登录 | 菜单/页面准入按新权限检查,后端也拒绝越权资源 |
| 移除写权限 | 保存按钮不可用,直接请求写 API 也被后端拒绝 |
| 注销或会话过期 | 撤销身份和业务内容,旧请求不能恢复旧用户 |
| CSRF 缺失或错误 | 服务端拒绝写请求,不通过关闭保护来解决 |
浏览器检查 Console 和 Network,不能仅凭构建成功判断生产接入完成。教学服务固定权限,不用于验证真实的多租户、角色管理和数据库事务;这些由实际后端验收。
仓库维护者:生产构建检查
在仓库根执行:
sh
pnpm check:production
pnpm --filter @axewo/fin-ui lint:check该流程验证当前生产范围内五个包的类型、构建、ESM/CJS 入口、声明引用和微前端发布清单,同时构建文档站及 playground,不发布 npm。测试用例与历史临时消费者工程已清理,fin-dashboard 与 fin-editor 暂不纳入生产范围。
生成或迁移项目后,仍须执行项目内的 check:runtime、typecheck 和 build,并按本章完成真实后台及部署验收。