preload 属性是浏览器加载建议而非开关;最稳妥默认值为 metadata,仅拉取视频头部信息,需服务端支持 Accept-Ranges 和 faststart 重写,iOS Safari 无视所有 preload 值。

preload 属性不是开关,而是浏览器的加载建议;设成 auto 不代表真会预加载,设成 none 也不等于零请求——关键在服务端支持、设备策略和 DOM 生命周期。
preload="metadata" 是最稳妥的默认值
它只拉取视频文件头部(moov box),用于获取时长、宽高、封面帧、音轨数等元信息,体积通常几 KB,响应快、失败影响小,且所有现代浏览器都严格遵守该行为。
- 必须确保服务端返回
Accept-Ranges: bytes响应头,否则浏览器可能退化为下载前几 KB 甚至整个文件才能解析元数据 - 视频文件需经
ffmpeg -c copy -movflags +faststart重写,否则 moov 在文件末尾,metadata模式会失效 - 配合
poster属性使用,能立刻显示占位图,避免白屏或闪烁 - 监听
loadedmetadata事件确认就绪,不要依赖video.readyState判断是否“已预加载”
iOS Safari 下 preload="auto" 完全无效
从 iOS 10 开始,Safari 将所有 preload 值(包括 auto)静默降级为 none,这不是 bug,是苹果强制的流量与电池策略。即使写了 autoplay,preload 也会被直接忽略。
-
video.readyState在 iOS 上长期卡在0(HAVE_NOTHING),直到用户点击播放才开始加载 - 不要用 UA 字符串检测 iOS 后再设
auto——写了也没用,不如省掉这行代码 - 微信 X5 内核更激进:哪怕设
none,只要调用play()就立即请求并缓存
动态修改 preload 基本不触发新加载
preload 属性只在 HTML 解析阶段参与资源调度;JS 动态插入的 <video></video> 元素,即使设置 preload="auto",也不会触发预加载。
- 真正可控的是:在
video.src赋值前设置preload,或在loadstart之前修改 - 想实现“即将进入视口时才加载”,应监听
IntersectionObserver,当目标可见后调用video.load() - 调用
load()后,需监听canplay或loadeddata才能安全展示控件或自动播放 - 若需更激进加载(如课程主视频),可搭配
<link rel="preload" as="video" href="xxx.mp4">主动发起请求(仅同域有效)
preload="none" 必须手动调用 load() 才生效
设成 none 后,video.src 赋值不会引发任何网络请求,连 DNS 查询都省了——但这也意味着你必须自己控制加载时机。
- 必须显式调用
video.load()才会发起请求,仅改src不够 - 移动端微信内置浏览器对首次
load()有延迟限制,可能被静默丢弃,建议加setTimeout微调 - 如果用户点了播放但还没调用
load(),浏览器会 fallback 加载,但体验割裂:进度条空白、无缓冲指示 - 列表页中的缩略视频(如短视频流)推荐用
none,避免拖慢渲染并浪费流量
真正起作用的从来不是 preload 的值本身,而是它背后的服务端配置、DOM 存在时机、以及你是否在正确节点上触发了 load()。别把优化寄托在一个 HTML 属性上。











