prefetch 不能直接预取视频文件,应预取下一集的元数据与控制逻辑,如html、脚本或代码分割后的chunk;动态注入比静态写死更高效,import()是更可靠替代方案。

prefetch 不能直接预取视频文件本身
写 <link rel="prefetch" href="next.mp4" as="video"> 是无效的。浏览器不支持 as="video",该值不在规范白名单中(合法值只有 script、style、document、image、font 等),会降级为 as="fetch",甚至被 Safari 静默忽略。视频文件体积大、带宽敏感,且 prefetch 不保证执行——用户划走、切后台、开省流模式时,请求直接被丢弃,还可能拖慢当前页播放缓冲。
真正该预取的是“下一集的播放元数据与控制逻辑”
点播场景下,用户点击“下一集”后真正耗时的不是拉视频,而是:请求新页面 HTML、解析 JS、获取播放配置(如 DRM token、CDN 路由、字幕地址)、初始化播放器实例。这些才是 prefetch 的合理目标:
-
as="document"预取下一集详情页 HTML(仅当该页是静态构建、无服务端 nonce/token) -
as="script"预取播放器核心模块或下一集专属业务逻辑(如/js/player-next.8a2b.js) -
as="json"不行——浏览器不识别;改用as="fetch"也不推荐,prefetch 不发 CORS 请求,跨域 JSON 接口大概率静默失败 - 若使用现代打包工具(Vite/Webpack),优先预取代码分割后的 chunk 文件路径,而非路由路径(比如预取
/assets/Episode2Player.4f9c.js,而不是/episode/2)
动态注入比静态写死更可控
在视频播放器 UI 上监听用户行为(如进度条拖到 90%、鼠标悬停“下一集”按钮),再延迟 200ms 注入 prefetch link,能显著降低误触发概率:
const prefetchNext = (url) => {
const link = document.createElement('link');
link.rel = 'prefetch';
link.as = 'script'; // 显式指定,避免降级
link.href = url;
document.head.appendChild(link);
};
<p>// 用户快看完时触发
video.addEventListener('timeupdate', () => {
if (video.currentTime > video.duration * 0.9 && !window.nextPrefetched) {
prefetchNext('/assets/Episode2Player.abcd123.js');
window.nextPrefetched = true;
}
});</p>
注意:不要在 中静态写死所有“下一集”链接——用户可能跳过、退出、或切换清晰度,硬编码会浪费流量,尤其在移动端 2G/3G 网络下。
比 prefetch 更简单可靠的替代方案是 import()
如果下一集播放逻辑已做代码分割(例如 React 中 const NextPlayer = lazy(() => import('./NextPlayer'))),直接调用 import('./NextPlayer') 即可。浏览器自动发起 runtime prefetch,优先级略高于 rel="prefetch",且无需手动管理 as、crossorigin 或路径拼接,Vite/Webpack 会 resolve 到真实 chunk 地址。它天然兼容 Chrome/Firefox/Safari(iOS 15+),规避了 Safari 对 as="document" 的长期支持缺陷。
复杂点在于:你得确认“下一集”的资源路径是构建时确定的、不可变的;一旦服务端返回动态 HTML 或带 nonce 的脚本,prefetch 缓存就失效——这种情况下,runtime import() 仍能工作,因为它不依赖 HTTP 缓存,而是走模块加载系统。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











