preload属性仅在HTML解析时生效,JS设置无效;metadata是唯一可靠值,但需服务端支持Accept-Ranges和MP4含faststart;iOS Safari强制降级为none,动态插入video需先挂载再调用load()。

preload 属性不是开关,浏览器经常忽略它;写在 HTML 里才可能生效,JS 后设 video.preload = "metadata" 完全不触发预加载。
preload="metadata" 是唯一靠谱的默认值
它只请求视频文件开头的元信息(比如时长、宽高、封面帧),不下载画面数据,兼容性好、带宽省、响应快。但有两个硬前提:
- 服务端必须返回
Accept-Ranges: bytes响应头,否则浏览器无法做字节范围请求,metadata模式可能退化成下载前几 KB 甚至整个文件 - MP4 文件必须用
ffmpeg -c copy -movflags +faststart重写,把moovbox 移到文件开头;否则浏览器得下完才能拿到元信息 - 搭配
poster使用,能立刻显示占位图,避免白屏或闪烁 - 监听
loadedmetadata事件确认就绪,别依赖video.readyState—— 尤其在 iOS 上,它长期卡在0(HAVE_NOTHING)
iOS Safari 的 preload 是摆设
从 iOS 10 开始,Safari 会把所有 preload 值(包括 auto)静默降级为 none,这不是 bug,是苹果强制的流量与电池策略。这意味着:
-
preload="auto"写了等于没写,别靠 UA 检测后动态加——写了也没用 -
video.readyState在用户点击播放前基本不动,canplay或loadeddata事件也不会触发 - 想让视频“进入视口再加载”,得用
IntersectionObserver监听可见性,然后显式调用video.load() - 调用
load()后,要等canplay才能安全展示控件或尝试自动播放
动态插入的 video 标签 preload 无效
只有初始 HTML 解析阶段的 <video preload="metadata"></video> 才可能触发预加载。JS 动态创建并插入 DOM 的 video 元素,无论怎么设 preload,浏览器都无视。
立即学习“前端免费学习笔记(深入)”;
真实场景中,懒加载组件、React/Vue 的条件渲染、SPA 路由切换后的视频,都属于这类。解决办法只有一个:
- 先插入带
src和preload="metadata"的video元素(哪怕暂时 display: none) - 等它进入视口或满足业务条件时,调用
video.load() - 若需更早发起网络请求,可配
<link rel="preload" as="video" href="xxx.mp4">(仅同域有效,且不触发解码)
最容易被忽略的是:preload 生效只在 HTML 解析那一瞬间;后续任何 JS 设置,都不会让浏览器回头去拉数据。如果你的视频是“滚动到才出现”的,那 preload 属性本身就没意义,得靠 load() + 事件驱动来补足。



















