Appearance
版本与 iframe 配置
进阶内容。日常接入用不到;上生产前确认部署方提供的 iframe 地址与精确版本即可。
有两个「版本」,别混
这是这一页最容易搞错的地方。
| 契约版本 | iframe 应用版本 | |
|---|---|---|
| 是什么 | host ↔ iframe 的通信协议版本 | 浏览器实际加载的 embed-app 构建版本 |
| 长什么样 | 4.1.0(严格 semver) | v1.0.25 |
| 在哪 | CONTRACT_VERSION 常量 | apps/embed-app/package.json 的 version |
| 谁改 | 改契约时走 ADR | iframe 产物可能变化时递增 |
一句话:version prop 控制你加载哪份 iframe 代码,契约版本控制两边能不能对话。
精确路径只使用 iframe 应用版本
/embed/v1.0.25/ 是一份固定 iframe 应用构建。协议版本写进该目录的发布清单, 用于判断握手兼容,但不决定 URL 路径。
URL 是怎么拼出来的
buildFrameUrl() → https://sentinel-video.pages.dev/embed/v1.0.25/
buildFrameUrl({ origin: 'https://x' }) → https://x/embed/v1.0.25/
buildFrameUrl({ version: 'v1.0.24' }) → https://sentinel-video.pages.dev/embed/v1.0.24/
buildFrameUrl({ version: '' }) → https://sentinel-video.pages.dev/优先级:显式 prop > 构建期 env > 硬编码默认。
VITE_SENTINEL_EMBED_ORIGIN 覆盖 origin
VITE_SENTINEL_EMBED_VERSION 覆盖 versionversion: '' 是给本地 dev server 用的 —— 它直接就在根路径,没有 /embed/vX/ 结构。
末尾那个斜杠是必须的
embed-app 用相对路径引资源(vite base: './'),URL 少了结尾 / 会 404。 buildFrameUrl 保证补上,自己拼 URL 时别漏。
固定版本与升级
| 写法 | 含义 | 现状 |
|---|---|---|
v1.0.25(默认) | 固定 iframe 应用构建 | ✅ 可用 |
v1.0.24 | 已发布的旧应用构建 | 仅在部署方保留该目录时可用 |
vue
<script setup lang="ts">
import { VideoPlayerFrame } from '@sentinel-lab/video-vue-frame'
const src = 'https://your-cdn/video.m3u8'
</script>
<template>
<VideoPlayerFrame :source="src" version="v1.0.25" />
</template>精确版本的留存由部署方保证
精确目录由部署方的发布记录决定。Cloudflare Pages 作为官方部署适配时不承诺历史目录永久可用。
升级 iframe 时,显式把 version 改为新的应用版本;固定版本不会自动收到修复。
部署方提供的 iframe 地址
默认地址不可用或业务环境另有安排时,由部署方提供 origin 与精确版本:
vue
<script setup lang="ts">
import { VideoPlayerFrame } from '@sentinel-lab/video-vue-frame'
const src = 'https://your-cdn/video.m3u8'
</script>
<template>
<VideoPlayerFrame :source="src" origin="https://player.your-company.com" />
</template>origin 是已部署 iframe 的位置,不是自建托管操作说明。Cloudflare 发布、验真与回滚由指定部署方负责。
CORS 方面:iframe 是同源加载自己的资源,不需要为 embed-app 配跨域; 但你的视频 CDN 需要允许播放器域名(见播不出来)。
握手时发生了什么
Penpal 连上之后,host 第一件事是调 iframe 的 handshake(hostVersion):
ts
handshake('4.0.0')
// → { iframeVersion: '4.0.0', compatible: true, warnings: [] }兼容规则由 protocol 的 isContractCompatible 统一定义 —— 两侧用同一个函数,各自实现一遍迟早会漂移:
ts
isContractCompatible('1.1.0', '1.4.0') // true · 1.x 的 minor 向后兼容
isContractCompatible('1.0.0', '2.0.0') // false · major 不同
isContractCompatible('0.1.0', '0.2.0') // false · 0.x 阶段 minor 就是破坏性的patch 差异永远兼容。
不兼容时走 version_incompatible 降级,并发出 E_HANDSHAKE_VERSION_MISMATCH(retryable: false —— 版本不对重试多少次都一样)。
四种握手失败,四个错误码
frame-core 把 iframe 起不来的原因映射成契约错误码,进 error 事件流, 所以监控看得到:
| 失败原因 | 错误码 | 常见成因 |
|---|---|---|
iframe_load_failed | E_LOAD_FAILED | URL 打不开、网络挂 |
csp_denied | E_ENV_CSP_BLOCKED | 你的页面 CSP 没放行播放器域名 |
handshake_timeout | E_HANDSHAKE_TIMEOUT | 15s 内没握上手 |
version_incompatible | E_HANDSHAKE_VERSION_MISMATCH | 契约 major 不匹配 |
两个超时值不一样,别记混:握手 15s,命令 10s。
升级时怎么办
- patch:自动,不用管
- minor:向后兼容的新增(新事件 / 新命令 / 新可选字段)。不监听、不调用即无影响
- major:破坏性,必须走 ADR + 迁移说明
契约冻结后每加一个事件或命令都要走 ADR —— 这不是流程洁癖, 是因为契约一旦漂移,五种接入方式的行为一致性就没法保证了。
已发生的三次「收回」记录在 ADR-032 / 033 / 034 里, 那三次删的都是契约里声明了但从来没实现过的东西。
相关
- ADR-023 · iframe URL 默认可覆盖
- 术语表 —— envelope / 握手 / Penpal 的准确定义
- iframe 专属排查