Стратегії завантаження ресурсів - preload, prefetch, modulepreload
Стратегії завантаження ресурсів — це техніки для оптимізації завантаження ресурсів у браузерах. Правильне використання preload, prefetch та інших підказок може значно прискорити завантаження сторінки.
Спектр стратегій завантаження
Критичний Шлях
Preload Потрібно зараз
Prefetch Потрібно незабаром
Prerender Наступна сторінка
Preload — Завантажити це негайно!
Мета: Завантажити критичні ресурси якнайшвидше.
Синтаксис Preload
<!-- Критичні шрифти -->
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<!-- Критичний CSS -->
<link rel="preload" href="/critical.css" as="style">
<!-- Зображення героя -->
<link rel="preload" href="/hero.jpg" as="image">
<!-- Модуль JavaScript -->
<link rel="preload" href="/app.js" as="script">Коли використовувати Preload
Добре:
<!-- Шрифти, що використовуються в критичному CSS -->
<link rel="preload" href="/fonts/heading.woff2" as="font" crossorigin>
<!-- Зображення LCP (Largest Contentful Paint) -->
<link rel="preload" href="/hero-image.jpg" as="image">
<!-- Критичний CSS (вище згинання) -->
<link rel="preload" href="/above-fold.css" as="style">Погано:
<!-- Не завантажуйте все! -->
<link rel="preload" href="/image1.jpg" as="image">
<link rel="preload" href="/image2.jpg" as="image">
<link rel="preload" href="/image3.jpg" as="image">
<!-- Це сповільнює завантаження! -->Типи ресурсів (як атрибут)
| Тип | Приклад |
|---|---|
script | Файли JavaScript |
style | Файли CSS |
font | Шрифти (потрібен crossorigin) |
image | Зображення |
fetch | Запити до API, JSON |
video | Відеофайли |
audio | Аудіофайли |
Prefetch — Завантажити, коли вільно
Мета: Завантажити ресурси для наступної навігації (низький пріоритет).
Синтаксис Prefetch
<!-- Сторінка, на яку користувач, ймовірно, перейде -->
<link rel="prefetch" href="/next-page.html">
<!-- JavaScript для наступної сторінки -->
<link rel="prefetch" href="/next-page.js">
<!-- Зображення, які з'являться при прокрутці -->
<link rel="prefetch" href="/below-fold-image.jpg">Коли використовувати Prefetch
Добре:
<!-- На сторінці продукту - попереднє завантаження кошика -->
<link rel="prefetch" href="/cart.js">
<!-- На цільовій сторінці - попереднє завантаження сторінки реєстрації -->
<link rel="prefetch" href="/signup">
<!-- У каруселі - попереднє завантаження наступного зображення -->
<link rel="prefetch" href="/carousel-image-2.jpg">Погано:
<!-- Не попередньо завантажуйте критичні ресурси для поточної сторінки! -->
<link rel="prefetch" href="/hero-image.jpg"> <!-- Має бути preload! -->Modulepreload — Preload для ES модулів
Мета: Preload для JavaScript модулів + їх залежностей.
Синтаксис Modulepreload
<!-- Завантажити модуль і його залежності -->
<link rel="modulepreload" href="/app.js">
<!-- Це також завантажить імпорти всередині app.js: -->
<!-- import { utils } from './utils.js' -->
<!-- import { api } from './api.js' -->Переваги Modulepreload
// app.js
import { helper } from './helper.js';
import { api } from './api.js';
// Без modulepreload:
// 1. Завантажити app.js
// 2. Розібрати app.js
// 3. Виявити імпорти
// 4. Завантажити helper.js і api.js Затримка!
// З modulepreload:
// 1. Завантажити app.js, helper.js, api.js паралельно
// 2. Розібрати та виконатиDNS-Prefetch — Розв'язати DNS раніше
Мета: Виконати DNS запит для зовнішнього домену.
Синтаксис DNS-Prefetch
<!-- Зовнішні ресурси -->
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://cdn.example.com">
<link rel="dns-prefetch" href="https://analytics.google.com">Економія часу
Без dns-prefetch:
Дія користувача → DNS запит (20-120ms) → Підключення → Запит
З dns-prefetch:
DNS вже готовий! → Підключення → Запит
Економія: 20-120msPreconnect — Встановити з'єднання раніше
Мета: DNS + TCP + TLS рукопожаття для зовнішнього домену.
Синтаксис Preconnect
<!-- Критичні зовнішні ресурси -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com">Що включає preconnect
1. DNS запит (20-120ms)
2. TCP рукопожаття (RTT)
3. TLS рукопожаття (RTT)
----------------------------
Загальна економія: 100-500ms!Preconnect vs DNS-Prefetch
| dns-prefetch | preconnect | |
|---|---|---|
| DNS запит | Так | Так |
| TCP рукопожаття | Ні | Так |
| TLS рукопожаття | Ні | Так |
| Вартість | Дешево | Дорожче |
| Коли | Багато доменів | Критичні домени (2-3) |
Підказки пріоритету
Атрибут fetchpriority контролює пріоритет завантаження:
<!-- Високий пріоритет для зображення LCP -->
<img src="/hero.jpg" fetchpriority="high">
<!-- Низький пріоритет для зображення нижче згинання -->
<img src="/footer-logo.jpg" fetchpriority="low" loading="lazy">
<!-- Критичний CSS -->
<link rel="stylesheet" href="/critical.css" fetchpriority="high">
<!-- Некритичний JavaScript -->
<script src="/analytics.js" fetchpriority="low" async></script>Пріоритети браузера (за замовчуванням)
| Ресурс | Пріоритет |
|---|---|
| HTML | Найвищий |
CSS (в <head>) | Найвищий |
| Шрифти | Високий |
Скрипти (в <head>) | Високий |
| Зображення (в полі зору) | Високий |
| Скрипти (async) | Низький |
| Зображення (нижче згинання) | Низький |
Критичні ланцюги запитів
Критичний ланцюг запитів — послідовність блокуючих ресурсів:
<!-- Погано: глибокий ланцюг -->
<html>
<head>
<link rel="stylesheet" href="/style.css">
<!-- У style.css: -->
<!-- @import url('/fonts.css'); -->
<!-- У fonts.css: -->
<!-- @font-face { src: url('/font.woff2'); } -->
</head>Глибина = 3:
- Завантажити style.css
- Розібрати → знайти fonts.css → завантажити
- Розібрати → знайти font.woff2 → завантажити
Рішення:
<!-- Добре: паралельне завантаження -->
<head>
<link rel="preload" href="/font.woff2" as="font" crossorigin>
<link rel="stylesheet" href="/style.css">
</head>
<!-- Глибина = 1, все паралельно! -->Практичні приклади
Інтернет-магазин
<head>
<!-- Критично для LCP -->
<link rel="preload" href="/hero-product.jpg" as="image" fetchpriority="high">
<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>
<!-- Критичні зовнішні ресурси -->
<link rel="preconnect" href="https://cdn.shopify.com">
<!-- Некритичні зовнішні -->
<link rel="dns-prefetch" href="https://analytics.google.com">
<!-- Prefetch для ймовірної навігації -->
<link rel="prefetch" href="/cart">
<link rel="prefetch" href="/checkout.js">
</head>SPA (Односторінковий додаток)
<!-- Preload критичних частин -->
<link rel="modulepreload" href="/app.js">
<link rel="modulepreload" href="/router.js">
<!-- Prefetch частин маршрутів -->
<link rel="prefetch" href="/routes/home.js">
<link rel="prefetch" href="/routes/about.js">Найкращі практики
- Preload тільки критичних ресурсів
Максимум 3-5 preload. Більше = конкуренція за пропускну здатність.
- Prefetch для передбачуваної навігації
Аналізуйте шлях користувача та попередньо завантажуйте ймовірні переходи.
- Preconnect до критичних CDN
Не більше 2-3 preconnect (дорожча операція).
- Використовуйте fetchpriority
Допоможіть браузеру пріоритизувати ресурси LCP.
- Вимірюйте вплив
Використовуйте Lighthouse, WebPageTest для валідації.
Інструменти аналізу
Chrome DevTools
Вкладка Мережа → Стовпець Пріоритет
Високий = Критичний шлях
Низький = Кандидати на PrefetchLighthouse
- "Preload ключових запитів"
- "Зменшити початковий час відповіді сервера"
- "Уникнути ресурсів, що блокують рендеринг"Резюме:
Правильне використання підказок ресурсів (preload, prefetch, preconnect) може зменшити час завантаження на 20-50%. Ключем є розуміння Критичного шляху та шляху користувача. Preload для критичних ресурсів, prefetch для ймовірних переходів, preconnect для зовнішніх API/CDN.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.