Реалізація Priority Hints для управління приоритетом завантаження ресурсів
Браузер сам розставляє приоритети завантаження, і більшу частину часу робить це правильно. Але є сценарії, де його евристики помиляються: LCP-зображення завантажується з низьким приоритетом, тому що находиться в каруселі та браузер не знає, що воно головне. Або скрипт аналітики отримує високий приоритет та затримує рендеринг. Priority Hints — атрибут fetchpriority — дає можливість скоригувати ці рішення.
Як браузер розставляє приоритети без підказок
Chrome використовує п'ять рівнів приоритету: Highest, High, Medium, Low, Lowest. За замовчанням:
- CSS у
<head>— Highest - Синхронні скрипти у
<head>— High - Зображення — Low (окрім перших в viewport — Medium)
- Async/defer скрипти — Low
- Fetch API — High
- XHR — High
Проблема в тому, що браузер не завжди знає, яке саме зображення є LCP-елементом. Якщо у <head> есть <link rel="preload"> для зображення — воно отримує High. Але це тільки прискорює його скачування, не змінюючи приоритет рендеринга.
Синтаксис fetchpriority
Атрибут приймає три значення: high, low, auto (за замовчанням).
<!-- Підвищуємо приоритет LCP-зображення -->
<img src="/hero.webp" fetchpriority="high" alt="Hero">
<!-- Знижуємо приоритет декоративних зображень ниже fold -->
<img src="/decoration.webp" fetchpriority="low" alt="">
<!-- Знижуємо приоритет некритичного скрипту -->
<script src="/analytics.js" defer fetchpriority="low"></script>
<!-- У preload-директиві -->
<link rel="preload" href="/hero.webp" as="image" fetchpriority="high">
У Fetch API:
// Критичний запит даних для першого рендера
const data = await fetch('/api/initial-data', { priority: 'high' });
// Фонова синхронізація
const sync = await fetch('/api/sync-status', { priority: 'low' });
Типовий сценарій: карусель зображень
Без підказок браузер не знає, що перше зображення карусель — це LCP-елемент. Завантажує всі зображення з одинаковим приоритетом.
<div class="carousel">
<!-- Перший слайд — LCP, високий приоритет -->
<img
src="/slides/slide-1.webp"
fetchpriority="high"
loading="eager"
alt="Слайд 1"
>
<!-- Інші слайди — низький приоритет або lazy -->
<img
src="/slides/slide-2.webp"
fetchpriority="low"
loading="lazy"
alt="Слайд 2"
>
</div>
Типовий сценарій: сторінка продукту з галереєю
<!-- Головне зображення — це LCP -->
<img
src="/products/main-image.webp"
fetchpriority="high"
loading="eager"
width="800"
height="600"
alt="Назва продукту"
>
<!-- Мініатюри — низький приоритет -->
<div class="thumbnails">
<img src="/products/thumb-1.webp" fetchpriority="low" loading="lazy" alt="">
</div>
Динамічне управління приоритетом у React
Коли LCP-елемент визначається динамічно:
function ProductGrid({ products }) {
return (
<div className="grid">
{products.map((product, index) => (
<ProductCard
key={product.id}
product={product}
imagePriority={index === 0 ? 'high' : 'low'}
imageLoading={index < 4 ? 'eager' : 'lazy'}
/>
))}
</div>
);
}
function ProductCard({ product, imagePriority, imageLoading }) {
return (
<div>
<img
src={product.image}
fetchpriority={imagePriority}
loading={imageLoading}
alt={product.name}
/>
</div>
);
}
У Next.js компонент <Image> використовує проп priority:
import Image from 'next/image';
// Автоматично додає fetchpriority="high" та preload
<Image
src="/hero.webp"
width={1200}
height={600}
priority
alt="Hero"
/>
Зниження приоритету сторонніх скриптів
Аналітика та пікселі не повинні конкурувати з критичними ресурсами:
<!-- З явно низьким приоритетом: -->
<script src="https://www.google-analytics.com/analytics.js" defer fetchpriority="low"></script>
<!-- GTM з низьким приоритетом -->
<script fetchpriority="low">
(function(w,d,s,l,i){/* GTM snippet */})(window,document,'script','dataLayer','GTM-XXXXX');
</script>
Критичні API-запити при SSR hydration
В SPA при hydration часто потрібно невідкладно отримати дані для першого рендера:
async function loadCriticalData(url) {
const response = await fetch(url, {
priority: 'high',
cache: 'no-cache',
});
return response.json();
}
async function syncUserPreferences() {
await fetch('/api/preferences', {
method: 'POST',
priority: 'low',
body: JSON.stringify(preferences),
});
}
Вимірювання ефекту
Перевіряємо через Chrome DevTools → Network → колона Priority. До та після розставлення fetchpriority дивимось:
- З яким приоритетом завантажується LCP-зображення
- Чи не витісняють сторонні скрипти критичні ресурси
Програмно — через PerformanceResourceTiming:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.initiatorType === 'img' && entry.name.includes('hero')) {
console.log({
url: entry.name,
ttfb: entry.responseStart - entry.fetchStart,
duration: entry.duration,
});
}
}
});
observer.observe({ type: 'resource', buffered: true });
Підтримка браузерами
fetchpriority підтримується в Chrome 101+, Edge 101+, Firefox 132+, Safari 17.2+. Для старих браузерів — просто ігнорується, graceful degradation.
Терміни
Аудит поточних приоритетів через DevTools та розставлення fetchpriority на ключових елементах — 4–8 годин. Повноцінне внедрення з динамічним управлінням приоритетом в React-компонентах — 1–2 робочих дні.







