preload 是协商信号而非开关,iOS Safari 强制忽略其值按 none 处理,Chrome 桌面版对 auto 实际等效 metadata;真正可控需 service端 faststart + HTML preload link + JS load() 显式调用。

preload 不是开关,而是协商信号;设了不等于加载,尤其在 iOS Safari 和弱网环境下几乎无效。
video 的 preload="auto" 为什么经常没反应
这不是你代码写错了,而是浏览器根本没按你说的做。iOS Safari 会无视所有 preload 值,强制当作 none 处理;Chrome 桌面版对 auto 的实际行为接近 metadata;部分安卓 WebView 甚至会忽略整个属性。
-
auto是最模糊的选项,浏览器可自由降级或跳过 - 即使设置了
preload="auto",若服务端未返回Accept-Ranges: bytes,浏览器仍可能卡在元数据加载阶段 - 移动端默认策略由系统决定,HTML 层面无法覆盖(比如微信内置浏览器、QQ 浏览器)
metadata 和 none 在真实网络下的区别
表面上看 metadata 只取头部,none 什么也不取,但现实更复杂:多数浏览器在 none 下仍会发一个 HEAD 或带 Range: bytes=0-1023 的请求,只为拿到视频宽高、时长、编码格式——这对封面图渲染和 UI 布局很关键,但用户并不感知。
-
metadata成功的前提是服务端支持字节范围请求;否则可能下载前几 KB 甚至整个文件才能解析出时长 -
none并非“零请求”,只是推迟到用户点击播放时才调用load()或触发自动加载 - 在 3G/4G 弱网下,
none能明显减少首屏流量,但首次点击后会有明显等待(尤其大视频)
真正可控的预加载手段:preload + load() + faststart
想让视频首帧快,光靠 <video preload="..."> 远不够。必须组合三层控制:
立即学习“前端免费学习笔记(深入)”;
- 服务端:用
ffmpeg -c copy -movflags +faststart把 MP4 的moovbox 移到文件开头,否则浏览器哪怕只取 metadata 也要扫完整个文件 - HTML 层:
<link rel="preload" href="video.mp4" as="video">(注意必须写as="video",不能省) - JS 层:在视口可见时显式调用
video.load(),并监听canplay事件防止重复触发
移动端 video 预加载最容易被忽略的点
不是参数没设对,而是整个加载时机模型被误判。移动端没有“后台预加载”概念:一旦页面不可见(比如切到其他 tab),浏览器大概率会中止或暂停视频加载,且不会恢复。所以依赖“提前加载完再播放”的逻辑在 iOS 上基本不可行。
- 不要给列表页所有
<video>都设preload="metadata",滚动时频繁创建/销毁 video 元素会导致内存泄漏和卡顿 - 用
loading="lazy"对<video>无效(该属性仅支持<img>和<iframe>),必须用 IntersectionObserver 手动控制 - 如果视频是核心内容(如首页 hero 视频),优先用 poster + 自动播放(
autoplay muted)+preload="auto"组合,比等用户点播更可靠



















