预览与构建链路
预览、截图与构建由 Backend 协调。Editor 发起用户操作,Runtime 提供页面渲染和构建能力;真实 Chromium 截图与页面诊断由独立 Renderer 执行。
页面预览
- Editor 保存页面源码或配置。
- Backend 校验用户权限和源码导入边界。
- Backend 创建 preview artifact,并为 Runtime 签发短期上下文令牌。
- Editor iframe 访问 Runtime 预览入口。
- Runtime 回源 Backend 读取上下文、配置包、资源和远程模块。
- Runtime 渲染页面并把结果展示给 Editor。
页面 iframe 使用版本 1 状态消息回传最终结果:成功发送 page-preview:ready,初始化或页面模块失败发送 page-preview:error;payload 必须包含当前 artifactId。Editor 同时校验消息窗口、origin、协议版本和 artifact,忽略旧预览迟到消息。Editor 在等待 8 秒后展示弱网提示,30 秒后进入可重试错误;超时不会销毁 iframe,因此同一 artifact 的迟到 ready 仍可恢复预览。
组件预览
组件预览依赖组件源码和 previewSchema。Backend 负责校验 previewSchema 可导入能力,Runtime 负责按 schema 渲染典型状态。previewSchema 变化时要同步 Runtime 组件预览测试和 Backend 契约测试。
组件预览沿用 component-preview:ready/error 消息,在 Editor 中采用与页面预览一致的 8 秒弱网提示和 30 秒可重试超时。刷新同一预览对象时保留旧 iframe 并覆盖加载状态;切换对象时清空旧画面,避免串用 artifact。
截图
- Backend 持久化渲染请求,并按租约和并发限制调度受信 Renderer。
- Renderer 为本次执行创建独立 Chromium 和 Context,加载 Runtime 的受保护预览页面。
- Renderer 等待页面就绪,生成截图或诊断结果并回传 Backend;Backend 关联任务与产物。
截图任务需要关注 viewport、超时、并发、资源加载和页面 visual-ready 状态。Backend 进程不直接启动浏览器。
项目构建
- 用户在 Editor 发起项目构建。
- Backend 创建
ProjectBuildJob持久任务(含attempt_id、租约字段和创建时即确定的绝对deadline_at)并生成 build snapshot。 runtime-build内的 Build Worker 按 project lane 并发启动等量领取消费者,通过POST /internal/runtime/build-jobs/claim以条件更新认领任务;Backend 下发 attempt 令牌,并把租约与令牌 TTL 一并裁剪到deadline_at之前。- Worker 执行期间周期调用
renew:收到 401/409 立即中止在跑构建,与 Backend 失联时也在本地租约到期(留出安全余量)前主动停手,避免失守的执行者继续消耗资源或抢写状态。 - Runtime 拉取 snapshot,生成临时入口并在隔离子进程内执行 Vite 构建与 ZIP 归档;构建子进程不继承 Worker 领取凭证。中止信号一路传到子进程本身:租约失守或 deadline 到期时先
SIGTERM,宽限 1 秒未退出再SIGKILL,并等到真实close才释放调度槽位与临时工作区。只中止主进程的fetch/sleep会让最耗 CPU 与内存的构建阶段继续跑到自然结束。 - Worker 以
POST /internal/runtime/build-jobs/{job_id}/artifact上传产物:归档按分块流直接作为请求体,入口文件与 sha256、大小通过x-runtime-build-archive-*头声明,两侧都不再把整包读进内存,Backend 超过PROJECT_BUILD_ARTIFACT_MAX_BYTES即中止写入。校验和/大小不符、attempt 围栏失守或提交异常时,Backend 会删除这个没有任何行引用的 attempt 归档,避免对象存储积累 orphan;仍被任务行引用的产物一律保留。上传成功后调用complete。Backend 只在attempt_id与有效租约同时匹配时才提升产物或写终态,失守的执行者只能留下等待恢复的running行。 complete(success)对同一attempt_id幂等:任务已是succeeded且产物已提升时返回 200 而不是 409,Runtime 侧对传输失败与 5xx 再做最多 3 次重试。否则「产物已上传、complete 响应丢失」只能等租约过期,用户会看到产物已生成但任务仍running十几分钟。4xx 是确定性拒绝,不重试。- 恢复循环按过期租约接管或收敛:已经上传产物的任务收敛为
succeeded,超过总期限仍未被领取的任务收敛为failed。
构建不存在第二跳执行路径:Backend 不再向 Runtime 同步派发构建,Runtime 也不暴露构建 HTTP 入口。凭证未配置时 Backend claim API fail-closed 且 Worker 不启动,构建任务停留在 pending 直到总期限把它收敛为失败。RUNTIME_ROLE=build 的容器在这种情况下直接启动失败,/__runtime_readyz 也不会就绪——「进程健康但永远不构建」比启动失败更难发现。
关键约束
- 页面源码、组件源码和 previewSchema 只能引用 Runtime Kit manifest 公开且版本化的能力。
- Runtime shell 内部能力不进入页面、组件或 AI 能力目录。
- 构建 snapshot 应固化当次构建所需上下文,避免构建过程中读取漂移状态。
- 预览 artifact 和构建心跳属于临时运行态,应有 TTL 和恢复策略。