preload="metadata"是最稳妥的默认值,仅拉取moov box获取元信息,需服务端支持accept-ranges且mp4经faststart重写,务必搭配poster和loadedmetadata监听;ios safari无视preload="auto",preload属性仅在html解析阶段生效。

preload="metadata" 是最稳妥的默认值
它只拉取视频文件开头的 moov box(通常几 KB),用于获取时长、宽高、封面帧、音轨数等元信息,不下载任何画面或音频数据。体积小、失败成本低、兼容性好,几乎所有现代浏览器都严格遵守。
但有两个硬前提必须满足,否则会退化为下载前几 KB 甚至整个文件:
- 服务端响应头必须包含
Accept-Ranges: bytes,否则浏览器无法发起字节范围请求 - MP4 文件需经
ffmpeg -c copy -movflags +faststart重写,确保moov在文件开头;否则浏览器得下完整个文件才能解析元数据 - 务必搭配
poster属性,避免白屏或闪烁 - 监听
loadedmetadata事件确认元信息就绪,不要依赖video.readyState初始值(它可能长期为 0)
iOS Safari 无视 preload="auto" 是铁律
从 iOS 10 开始,Safari 会静默将所有 preload 值(包括 auto)降级为 none。这不是 bug,是苹果强制的流量与电池策略。哪怕你写了 preload="auto",也等于没写。
更关键的是:只要设置了 autoplay,preload 就直接被忽略——这是 HTML5 规范行为,不是浏览器 bug。
常见错误做法:
- 用 UA 字符串检测 iOS 后再设
preload="auto"—— 写了也没用 - 在 JS 中动态设置
video.preload = "auto"—— 只对尚未开始加载的元素有效,且仅在 HTML 解析阶段起作用 - 指望
auto能触发canplaythrough或保证首帧秒出 —— 它不承诺任何加载量
preload="none" 必须配合 IntersectionObserver 手动 load()
设成 none 后,video.src 赋值不会触发任何网络请求,video.readyState 长期为 0(HAVE_NOTHING)。它真能省流,但代价是首次点击播放会有明显延迟。
所以不能只写 preload="none" 就完事,必须主动控制加载时机:
- 用
IntersectionObserver监听视频是否即将进入视口,可见后立即调用video.load() - 微信 X5 内核对首次
load()有静默丢弃风险,建议加setTimeout(() => video.load(), 0)微调 - 不要给信息流中所有视频都设
none却不监听视口 —— 用户滑到眼前才开始拉流,体验卡顿 - Chrome 对小 MP4 可能仍会预读前几百 KB,别误以为 “绝对零请求”
静态 HTML 中的 preload 才真正生效
preload 属性只在 HTML 解析阶段参与资源调度。它是浏览器早期资源发现机制的一部分,不是运行时开关。
这意味着:
- React/Vue 渲染的视频组件,即使模板里写了
preload="metadata",也不会触发预加载 - JS 动态插入的
<video></video>元素,preload属性完全无效 - 真正可控的做法是:首屏核心视频用静态 HTML +
preload="metadata"+poster;滚动列表中的视频靠IntersectionObserver+preload="none"+ 显式load() - 想更激进加载,可搭配
<link rel="preload" as="video" href="xxx.mp4">(仅同域有效),但它不触发解码,也不影响video元素自身状态
真正难控的从来不是怎么写 preload,而是浏览器如何解释它——同一段 HTML,在 Chrome Desktop、iOS Safari、微信 Android WebView 上的行为可能完全不同。最常被忽略的点,是误把 preload 当成运行时指令,却没意识到它只在 HTML 刚解析那几十毫秒内起作用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











