如何用BOM实现页面的预加载?

来源:Golang编程网作者:小何头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何用BOM实现页面的预加载?》,敬请观看详情。浏览器对象模型提供了一组与文档无关的接口,其中部分能力可被用来提前获取后续页面所需资源。常见做法是借助DOM中的link元素设置rel为prefetch或preload,配合window对象的事件钩子控制触发时机。与单纯依赖浏览器自动推测不同,手动通过脚本插入预加载节点能更精准地命中用户下一步访问路径。需要注意的是,prefetch用于空闲时低优先级加载,preload则会立即高优先级请求,误用容易造成带宽浪费。结合visibilitychange与load事件,可以在首屏稳定后悄悄拉取疑似目标页,从而缩短实际跳转时的白屏时间。

页面预加载的核心目标是减少用户跳转时的等待感。BOM本身并没有一个名为preload的专用方法,但我们可以通过操作document、window等BOM相关对象,在脚本中动态创建资源请求,从而达成预加载效果。通常的思路是:等当前页面核心内容渲染完毕,再利用浏览器的空闲带宽去提前获取下一页的HTML、CSS或脚本。

如何用BOM实现页面的预加载?

一、利用link标签与rel属性

在BOM体系中,document对象允许我们动态创建<link>节点。通过给link设置rel="prefetch"或rel="preload",可以通知浏览器提前获取指定资源。prefetch是低优先级、浏览器空闲时才执行的预取;preload则是高优先级、立刻发起的请求,适合当前页面马上要用的关键子资源。

下面示例在页面加载完成后,动态插入一个prefetch链接,提前拉取列表页可能跳转到详情页的HTML:

window.addEventListener('load', function () {
  // 当前页面onload后再考虑预加载,避免抢占首屏资源
  var link = document.createElement('link');
  link.rel = 'prefetch';
  link.href = '/article/detail/123';
  document.head.appendChild(link);
});

如果下一页依赖某个独立的JS模块,也可以改用preload并声明as类型,让浏览器以正确方式缓存:

function preloadScript(url) {
  var link = document.createElement('link');
  link.rel = 'preload';
  link.as = 'script';
  link.href = url;
  document.head.appendChild(link);
}
preloadScript('/static/js/detail.js');

二、结合页面可见性控制触发时机

无脑预加载可能浪费流量,尤其在移动网络下。我们可以利用window的visibilitychange事件,仅在用户停留且页面处于前台时触发。BOM的document.visibilityState能告诉我们页面是否被隐藏,从而避免在后台标签页里做无用请求。

以下代码展示了如何仅在页面可见且加载完成一段时间后,才预取可能的下一页:

document.addEventListener('visibilitychange', function () {
  if (document.visibilityState !== 'visible') {
    return;
  }
  if (document.readyState === 'complete') {
    var link = document.createElement('link');
    link.rel = 'prefetch';
    link.href = '/user/center';
    document.head.appendChild(link);
  }
});

这种方式的优点是:即使用户打开多个标签页,也只会对真正露出的页面执行预加载。缺点在于,如果用户快速跳转,可能还没来得及 prefetch 就已经离开,因此更适合停留时长较长的内容页。

三、通过fetch与缓存配合做软预加载

除了link标签,我们也能用window.fetch主动请求下一页HTML并放入内存或Service Worker缓存。虽然fetch属于Web API而非严格意义的BOM属性,但它挂载在window上,是BOM环境提供的全局方法。这种做法能让我们对响应内容做校验,只缓存合法页面。

示例代码如下,在用户鼠标悬停某个链接时提前fetch,不依赖浏览器推测:

var hoverTimer = null;
document.querySelectorAll('a.next-page').forEach(function (a) {
  a.addEventListener('mouseenter', function () {
    hoverTimer = setTimeout(function () {
      fetch(a.href, { mode: 'no-cors' }).catch(function () {});
    }, 200);
  });
  a.addEventListener('mouseleave', function () {
    clearTimeout(hoverTimer);
  });
});

该方案的精度较高,因为悬停往往代表点击意图。但需要注意no-cors模式下无法读取响应内容,只能借助HTTP缓存生效。若站点接入了Service Worker,可在fetch事件中cache.put,实现真正的离线预载。

四、方案对比与注意点

不同预加载手段各有适用场景,盲目使用反而会拖慢首屏。我们通过一个简表来比较:

方式优先级触发控制适用情况
link rel=prefetch浏览器空闲下一步页面不确定但概率高
link rel=preload立即当前页即将用到的子资源
window.fetch脚本控制交互明确如悬停、停留

最后要提醒,预加载不是越多越好。应当基于用户行为埋点找出高频路径,只对核心跳转链做预取。同时留意浏览器并发限制,避免预加载阻塞正在进行的接口请求。通过BOM提供的事件与全局方法,我们完全可以用少量代码让站点体验更顺滑。

BOM页面预加载link_rel_prefetch修改时间:2026-08-09 06:21:26

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。