Skip to content

版本与 iframe 配置

进阶内容。日常接入用不到;上生产前确认部署方提供的 iframe 地址与精确版本即可。


有两个「版本」,别混

这是这一页最容易搞错的地方。

契约版本iframe 应用版本
是什么host ↔ iframe 的通信协议版本浏览器实际加载的 embed-app 构建版本
长什么样4.1.0(严格 semver)v1.0.25
在哪CONTRACT_VERSION 常量apps/embed-app/package.jsonversion
谁改改契约时走 ADRiframe 产物可能变化时递增

一句话: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   覆盖 version

version: '' 是给本地 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_failedE_LOAD_FAILEDURL 打不开、网络挂
csp_deniedE_ENV_CSP_BLOCKED你的页面 CSP 没放行播放器域名
handshake_timeoutE_HANDSHAKE_TIMEOUT15s 内没握上手
version_incompatibleE_HANDSHAKE_VERSION_MISMATCH契约 major 不匹配

两个超时值不一样,别记混:握手 15s,命令 10s


升级时怎么办

  • patch:自动,不用管
  • minor:向后兼容的新增(新事件 / 新命令 / 新可选字段)。不监听、不调用即无影响
  • major:破坏性,必须走 ADR + 迁移说明

契约冻结后每加一个事件或命令都要走 ADR —— 这不是流程洁癖, 是因为契约一旦漂移,五种接入方式的行为一致性就没法保证了。

已发生的三次「收回」记录在 ADR-032 / 033 / 034 里, 那三次删的都是契约里声明了但从来没实现过的东西。


相关