preload="video"仅对同域视频生效,跨域必须加crossorigin;它只触发下载不触发解码,与<video preload>互不互通;iOS Safari中实际无效,无法复用缓存。

preload="video" 只对同域视频生效,跨域必须显式加 crossorigin
浏览器把 as="video" 当作 fetch 请求处理,默认不带凭据(anonymous 模式),哪怕视频和页面同源,也必须加 crossorigin 属性,否则预加载会静默失败——Network 面板里能看到请求发出去了,但状态码是 0,资源进不了缓存池。
常见错误写法:<link rel="preload" href="https://cdn.example.com/video.mp4" as="video"> —— 缺少 crossorigin,Safari 和 Chrome 都会丢弃响应;正确写法是:<link rel="preload" href="https://cdn.example.com/video.mp4" as="video" crossorigin>。
如果服务端返回的响应头不含 Access-Control-Allow-Origin,即使加了 crossorigin,也会被浏览器拦截,此时 Network 面板显示 CORS 错误,且不会缓存。
preload 触发的是下载,不是解码,也不影响 video 元素状态
<link rel="preload" as="video"> 的作用仅限于提前建立连接、发起 HTTP 请求、把字节流存入 HTTP 缓存。它不会触发视频解码,也不会让关联的 <video> 元素自动进入 canplay 或 loadedmetadata 状态。
立即学习“前端免费学习笔记(深入)”;
这意味着:即使你写了 preload,video.readyState 仍可能长期为 0(HAVE_NOTHING),尤其在 iOS Safari 上;必须等用户交互或显式调用 load() 后,元素才开始解析元数据或帧数据。
所以不要指望 preload 后直接 play() 就能成功——得监听 canplay 或 loadeddata 事件再操作,否则大概率报错 DOMException: The element has no supported sources。
preload="video" 和 video.preload 属性完全不互通
<link rel="preload"> 是 HTML 解析阶段的独立资源调度指令,而 <video preload="metadata"> 是元素自身的加载策略建议,两者生命周期、触发时机、作用范围互不感知。
以下情况毫无效果:
- 动态 JS 创建
<video>后再补写preload="auto" - 页面初始没渲染
<video>,只靠linkpreload,期望后续插入时自动复用 - 写了
link preload却没在 HTML 中声明<video>,以为“资源有了就能用”
真正可控的做法是:确保 <video> 在初始 HTML 中存在(哪怕 display: none),并配合 preload="metadata" + faststart 视频 + Accept-Ranges: bytes 响应头;link preload 只作为同域下的带宽抢跑补充,不能替代元素级控制。
移动端 iOS Safari 下 preload="video" 实际无效,别依赖它
iOS Safari(所有版本)对 <link rel="preload" as="video"> 的支持是空实现——它会发出请求,但不会把响应体存入可复用的媒体缓存区;即使 Network 面板看到 200,后续 <video> 加载时仍会重新发起完整请求。
这不是 bug,是苹果明确的策略:禁止预加载视频以节省电池与流量。验证方法很简单:在 iOS Safari DevTools(通过 macOS Safari 远程调试)中查看 Network,筛选 Initiator = preload 的请求,再检查该视频 URL 在后续 <video> load 时是否复用——几乎从不复用。
如果你的目标用户大量使用 iOS 设备,link preload 对视频的收益趋近于零,应把优化重心放在:faststart 重写、poster 占位、IntersectionObserver + load() 懒加载触发、以及服务端 Range 支持这四件事上。



















