仅在良好的网络条件下和可用的设备上进行预取。
预取策略
预取已经存在一段时间了,但谨慎使用它很重要,因为它会为并非立即需要的资源消耗额外的带宽。应谨慎应用此技术,以避免不必要的数据使用。
如果满足以下条件,则会预取文章:
- 预取文章链接的可见性: 使用Intersection Observer API来检测包含要预取的文章的部分的可见性。
- 增加数据使用的有利条件:如前所述,预取是一种推测性性能改进,会消耗额外的数据,并且在每种情况下都可能不是理想的结果。为了减少浪费带宽的可能性,使用网络信息 API和设备内存 API来确定是否获取下一篇文章。 仅在以下情况下获取下一篇文章:
- 连接速度至少为3G,设备内存至少为4GB,
- 或者如果设备运行的是 iOS。
- CPU 空闲:最后,Terra 使用 来检查 CPU 是否空闲并且能够执行额外的工作requestIdleCallback,这会在主线程空闲时或在特定(可选)截止日期之前处理回调(以先到者为准)。
遵守这些条件可确保 仅在必要时获取数据,从而节省带宽和电池寿命,并最大限度地减少最终未使用的预取的影响。JavaScript实现
function prefetch(nodeLists) { // Exclude slow ECTs < 3g if (navigator.connection && (navigator.connection.effectiveType === 'slow-2g' || navigator.connection.effectiveType === '2g') ) { return; }
// Exclude low end device which is device with memory <= 2GB if (navigator.deviceMemory && navigator.deviceMemory <= 2) { return; }
const fetchLinkList = {};
const observer = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting) { if (!fetchLinkList[entry.target.href]) { fetchLinkList[entry.target.href] = true;
fetch(entry.target, { priority: 'low' }); }
observer.unobserve(entry = entry.target); } }); }); }
const idleCallback = window.requestIdleCallback || function (cb) { let start = Date.now();
return setTimeout(function () { cb({ didTimeout: false, timeRemaining: function () { return Math.max(0, 50 - (Date.now() - start)); } }); }, 1); }
idleCallback(function () { prefetch(nodeLists) })
|
- 在启动预取之前,预取函数首先会检查最低连接质量和设备内存。
- 然后,它使用 IntersectionObserver 监视视口中的元素何时可见,随后将 URL 添加到列表中进行预取。
- 预取过程通过 requestIdleCallback 进行调度,目的是在主线程空闲时执行预取函数。