Skip to content

ADR-023: iframe URL 默认 + 可覆盖

Status: Accepted Date: 2026-07-13

Context

iframe 模式需要一个 URL。是硬编码?让消费方每次填?还是有默认?

Decision

frame-core 内默认 https://sentinel-video.pages.dev,消费方通过 origin / version props 覆盖。

CDN 路径规范:

  • /embed/v1/ — 最新 v1.x.x(默认引用)
  • /embed/v1.2/ — 锁 minor
  • /embed/v1.2.3/ — 锁死具体版本

embed-app 需支持双通信模式:

  • Penpal RPC(SDK 场景,双向)
  • 原生 postMessage(静态场景,单向广播)

Rationale

  • 默认 URL 让消费方 zero-config 就能跑
  • origin 覆盖支持私有化部署
  • version 覆盖支持版本锁定(防上游意外变更)

Consequences

:

  • 消费方零配置起步
  • 私有化 / 版本锁 灵活
  • CDN 路径规范清晰

代价:

  • 需要维护默认 CDN 域名
  • 版本策略需要文档化

Update (2026-07-15): 构建期 env 默认(第三层覆盖)

背景:接 examples/team-video-vueapps/playground-vue 时发现,LivePreviewCard / VideoPageWithRec 这类封装组件不透传 origin,本地开发会回退到硬编码 CDN sentinel-video.pages.dev(线上域名),导致 iframe 加载失败。且生产多环境 (staging CDN ≠ prod CDN)也需要"整个 app 一次性指向某个 embed origin",给每个封装组件 逐个传 origin 不可行。

决策:在 origin prop 之外,增加一层构建期 env 默认buildFrameUrl 的解析优先级:

显式 origin/version 参数(props)  >  构建期 env  >  硬编码 CDN 默认

env 变量:

  • VITE_SENTINEL_EMBED_ORIGIN — 覆盖默认 origin
  • VITE_SENTINEL_EMBED_VERSION — 覆盖默认 version 段(空串 = dev server 根路径,无 /embed/vX/)

读取方式(packages/frame-core/src/url-builder.tsreadEnv):

  • 浏览器 / Vite 客户端:import.meta.env.VITE_*(消费方构建期静态替换)
  • node / SSR(Nuxt)/ 单测:process.env.VITE_* 兜底

为什么仍属 ADR-023:这是"可覆盖"的延伸,不改协议 schema、不改公开类型签名、向后兼容 (env 未设时行为与原来完全一致)。它把"覆盖"的粒度从"每组件"补齐到"每 app/每环境"。

消费方用法:app 根目录放 .env.<mode>,例如 playground-vue 的 .env.development 指向 http://localhost:5174;cend-p0 的各环境 .env 指向对应 CDN。

References

  • USER-GUIDE.md § 26(iframe URL 详细说明)
  • packages/frame-core/src/url-builder.ts(readEnv + buildFrameUrl 解析优先级)
  • apps/playground-vue/.env.development(本地 dev 覆盖示例)