概念概述
Fetch Priority 取数优先级(Fetch Priority Signals)指的是:fetchpriority 属性告知浏览器哪些资源更重要,使其在网络取数时重排顺序,让关键图片先于低价值任务加载。
从更严格的定义看,Fetch priority is a hint, expressible as an HTML attribute or a JavaScript option, that raises or lowers a resource’s scheduling priority relative to the browser’s default assumption. 该概念在工程实践中的价值,在于它能帮助团队用统一的语言描述一个具体的质量属性或设计约束,从而在评审与协作中减少歧义。
为什么需要它
It is used to accelerate the largest contentful paint image or defer below-the-fold media during load. 它与 Speculative Parsing and Preload Scanner、Render-Blocking Resources、Native ES Modules in the Browser 等概念经常一起出现,用于解决相近的工程问题。理解它的适用场景,有助于在多种备选方案之间做出有依据的取舍,而不是凭直觉选择技术方案。
常见误解
- fetchpriority guarantees a faster transfer
- it changes the order in which the HTML parser encounters elements
需要避免的反模式
- marking every image as high priority so none stands out
- lowering priority on resources that block the first render
实践要点
- Browsers derive a default priority per resource type, and fetchpriority lets the author override that judgement based on layout knowledge the browser lacks.
- Setting high priority on a hero image often improves the largest contentful paint, while downgrading non-critical media frees bandwidth for scripts and styles.
- The hint only influences scheduling among competing fetches; it cannot overcome a slow origin or a bandwidth limit, so it works best alongside proper caching and compression.
参考来源
https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/fetchpriority
代码示例
<!-- Native lazy loading -->
<img src="hero.jpg" alt="Hero" loading="eager" width="1200" height="600">
<img src="image1.jpg" alt="Image 1" loading="lazy" width="400" height="300">
<img src="image2.jpg" alt="Image 2" loading="lazy" width="400" height="300">
<img src="image3.jpg" alt="Image 3" loading="lazy" width="400" height="300">
<iframe src="video-player.html" loading="lazy"
width="560" height="315"
title="Video player"></iframe>
<!-- With fade-in effect -->
<img class="lazy-img"
src="placeholder.svg"
data-src="actual-image.jpg"
alt="Description"
width="400" height="300">
<style>
.lazy-img {
opacity: 0;
transition: opacity 0.3s;
}
.lazy-img.loaded {
opacity: 1;
}
</style>
<script>
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.add('loaded');
observer.unobserve(img);
}
});
}, {
rootMargin: '50px 0px',
threshold: 0.01
});
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});
} else {
document.querySelectorAll('img[data-src]').forEach(img => {
img.src = img.dataset.src;
});
}
</script>