Preload, prefetch і preconnect: коли кожен із них справді допомагає
Resource hints корисні тоді, коли відповідають реальним вузьким місцям у браузері. Якщо застосовувати їх навмання, вони додають шуму в пріоритетах і часом сповільнюють сторінки.
Зміст
- Resource hints — не магія
- Що браузер уже робить добре
- Preload: для ресурсів поточної сторінки, виявлених надто пізно
- Preload і LCP-зображення
- Prefetch: для наступної сторінки, а не цієї
- Preconnect: для дорогих з’єднань із важливими origin
- DNS-prefetch: легший родич
- Як ухвалювати рішення: практичний workflow
- 1. Визначте вузьке місце
- 2. Додавайте по одній підказці
- 3. Перевірте побічні ефекти пріоритетів
- 4. Перевірте заголовки й кешування
- Поширені помилки
- Preloading надто великої кількості ресурсів
- Використання prefetch для обов’язкових ресурсів
- Preconnecting до кожного стороннього сервісу
- Ігнорування мобільних умов
- Проста таблиця рішень
- Спокійне правило
Resource hints — не магія
preload, prefetch і preconnect часто сприймають як чекліст продуктивності. Додати кілька тегів у <head>, ще раз запустити Lighthouse, відчути полегшення. Але вони працюють не так.
Ці підказки — інструкції для конвеєра завантаження браузера. Вони можуть допомогти, коли ви знаєте щось, що браузер не може виявити достатньо рано. І можуть зашкодити, коли ви вгадуєте, надмірно підвищуєте пріоритет некритичної роботи або прогріваєте з’єднання, які користувачам ніколи не знадобляться.
Коротко:
- Використовуйте
preloadдля ресурсів, потрібних поточній сторінці, але виявлених надто пізно. - Використовуйте
prefetchдля ймовірних ресурсів майбутньої навігації, а не для необхідного на поточній сторінці. - Використовуйте
preconnectдля важливих сторонніх origin, де встановлення з’єднання справді створює затримку.
Практичне питання не в тому, «яка підказка найшвидша?». А в тому, «на що чекає браузер, і чи може ця підказка усунути це очікування?»
Що браузер уже робить добре
Сучасні браузери — не пасивні завантажувачі файлів. Вони парсять HTML, заздалегідь сканують ресурси, призначають пріоритети, повторно використовують з’єднання, відкладають роботу, яка не видима, і адаптуються до умов мережі.
Тому resource hints мають бути вибірковими. Якщо таблицю стилів, скрипт, зображення або шрифт уже виявлено рано й із правильним пріоритетом, додаткова підказка може нічого не змінити. Гірше того, вона може конкурувати з ресурсами, які важливіші.
Перш ніж додавати підказки, подивіться на waterfall trace у DevTools або лабораторний звіт. Якщо ви використовуєте Lighthouse, починайте з діагностик, а не з оцінки; у нас є окремий посібник про те, як читати звіт Lighthouse без паніки — але зверніть увагу, що правильний URL чутливий до регістру, тож за потреби використовуйте посилання на статтю з навігації вашого сайту.
Справжні докази зазвичай видно в трьох місцях:
- Критичний ресурс стартує пізно, бо браузер виявляє його пізно.
- З’єднання з важливим origin займає помітний час перед першим запитом.
- Ресурс наступної сторінки дуже передбачуваний і його дешево завантажити під час простою.
Якщо нічого з цього не справджується, підказка, ймовірно, лише декорація.
Preload: для ресурсів поточної сторінки, виявлених надто пізно
preload повідомляє браузеру: «Завантаж цей ресурс зараз, бо він знадобиться поточній сторінці».
Типовий приклад — вебшрифт, на який посилаються всередині CSS. Браузер має завантажити HTML, виявити CSS, завантажити CSS, розпарсити його, виявити шрифт і лише тоді запросити шрифт. Якщо цей шрифт важливий для тексту у видимій без прокручування області, виявлення може бути настільки пізнім, що спричинить зсуви макета або затримку відображення тексту.
Preload може перенести цей запит раніше:
<link rel='preload' href='/fonts/inter-var.woff2' as='font' type='font/woff2' crossorigin>
Атрибут as важливий. Він повідомляє браузеру, що це за тип ресурсу, а це впливає на пріоритет, кешування, content security policy і заголовки запиту. Шрифтам також зазвичай потрібен crossorigin, навіть коли вони віддаються з того самого сайту, бо завантаження шрифтів використовує режим CORS.
Хороші кандидати для preload:
- Основний вебшрифт, який використовується для видимого тексту.
- Hero image, що є елементом Largest Contentful Paint і не виявляється рано.
- Критичний CSS-файл, завантажений опосередковано.
- Модуль або скрипт, потрібний дуже рано, але прихований за іншим скриптом.
Погані кандидати для preload:
- Кожна вага шрифту в дизайн-системі.
- Зображення нижче першого екрана.
- Скрипти, не потрібні для початкового рендерингу.
- Ресурси, які браузер уже виявляє в першому фрагменті HTML.
Preload потужний, бо впливає на пріоритети поточної сторінки. Саме тому його легко використати неправильно. Якщо ви preload’ите п’ять великих ресурсів, ви вже не допомагаєте браузеру. Ви з ним сперечаєтеся.
Шрифти — класичний випадок. Preload одного основного файлу шрифту може допомогти. Preload шести ваг і курсивів зазвичай погіршує ситуацію. Якщо шрифти — ваше вузьке місце, спершу впорядкуйте набір шрифтів; наш посібник про те, чому web fonts are still the easiest performance win on most sites, докладніше пояснює таке прибирання.
Preload і LCP-зображення
Preload LCP-зображення може бути корисним, коли зображення не видно в початковому HTML. Поширені причини — CSS background images, компоненти з клієнтським рендерингом або логіка responsive images, яка з’являється пізно.
Але якщо ваш hero image уже є в HTML як <img> із доречними srcset, sizes, розмірами й без lazy loading, браузер, імовірно, швидко його знайде. У такому разі додавання fetchpriority='high' може бути доречнішим за preload — залежно від сторінки.
Хороший тест: якщо запит зображення стартує пізно у waterfall і стає LCP-елементом, розгляньте preload. Якщо він стартує рано, але завантажується повільно, проблема в розмірі, форматі, поведінці CDN або затримці сервера — не у виявленні. Про вибір форматів зображень дивіться when AVIF beats WebP and when it does not.
Prefetch: для наступної сторінки, а не цієї
prefetch повідомляє браузеру: «Цей ресурс може скоро знадобитися, але він не потрібен прямо зараз».
Ця відмінність важлива. Prefetch навмисно має низький пріоритет. Браузер може завантажити його під час простою й зберегти для подальшого використання. Він також може пропустити його на поганому з’єднанні, у режимах економії даних або під тиском пам’яті.
Використовуйте prefetch, коли намір користувача достатньо сильний, щоб наступний ресурс був імовірним.
Хороші кандидати для prefetch:
- Наступний крок у багатосторінковому checkout.
- Результати пошуку після того, як користувач почав вводити запит, якщо наступний route передбачуваний.
- Сторінки документації, на які посилається зміст, коли користувач активно читає сусідній контент.
- Route chunks у single-page app після hover або focus на елементі навігації.
Погані кандидати для prefetch:
- Усе ваше дерево навігації.
- Великі відео або галереї зображень.
- Сторонні скрипти «про всяк випадок».
- Сторінки, на які користувачі рідко переходять далі.
Prefetch — це місце, де стриманість окупається. Ресурс, який завантажили й ніколи не використали, не є безкоштовним. Він споживає пропускну здатність, ресурси сервера, енергію і, можливо, дані користувача. У мобільних мережах спекулятивне завантаження може бути відверто недружнім.
Для багатьох сайтів найкраща стратегія prefetch — на основі наміру. Не prefetch’те сторінку з цінами одразу після завантаження домашньої сторінки. Prefetch’те її, коли користувач відкриває меню з цінами, наводить курсор на посилання з цінами або прокручує до call-to-action, який сильно прогнозує навігацію.
Також пам’ятайте, що поведінка браузерів різниться. Деякі браузери обережні з prefetch; деякі налаштування приватності зменшують або вимикають спекулятивне завантаження. Сприймайте prefetch як опортуністичне покращення, а не як механізм коректності.
Preconnect: для дорогих з’єднань із важливими origin
preconnect повідомляє браузеру: «Почни встановлювати з’єднання з цим origin зараз».
Це може включати DNS lookup, TCP connection і TLS negotiation. Для сторонніх origin така підготовка може займати сотні мілісекунд, особливо в мережах із високою затримкою. Якщо сторінці невдовзі потрібен критичний запит із цього origin, preconnect може пришвидшити подальший запит.
Приклад:
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
Хороші кандидати для preconnect:
- Font origin, що використовується для render-blocking тексту.
- Критичний API origin, потрібний під час початкової взаємодії.
- CDN origin, який віддає ресурси у видимій без прокручування області.
- Провайдер платежів або ідентифікації, потрібний одразу після дії користувача.
Погані кандидати для preconnect:
- Analytics і advertising endpoints, які не є критичними для користувача.
- Origin, що використовуються лише в частині сесій.
- Довгі списки сторонніх сервісів.
- Same-origin ресурси, де браузер уже має або скоро відкриє з’єднання.
Preconnect має вартість утримання. Відкриті сокети споживають пам’ять і мережеві ресурси. Браузери закриватимуть невикористані з’єднання, але це не робить зайві preconnect нешкідливими.
Корисне правило: робіть preconnect максимум до одного-двох сторонніх origin із високою впевненістю на сторінці. Якщо хочеться додати більше, вашій сторонній архітектурі, ймовірно, потрібен перегляд більше, ніж вашим підказкам — розширення.
DNS-prefetch: легший родич
Ви також можете побачити dns-prefetch:
<link rel='dns-prefetch' href='https://example-cdn.com'>
Він лише резолвить доменне ім’я. Він не відкриває TCP або TLS connection. Він дешевший за preconnect, але й менш корисний.
DNS-prefetch може бути доречним для сторонніх origin із нижчою впевненістю, де повний preconnect здається надто агресивним. На практиці, якщо origin критичний і точно скоро використовується, надавайте перевагу preconnect. Якщо це лише можливо, використовуйте DNS-prefetch або не робіть нічого.
Як ухвалювати рішення: практичний workflow
Починайте з вимірювання, а не з тегів.
1. Визначте вузьке місце
Відкрийте performance trace і шукайте пізнє виявлення. Чи запит шрифту, hero image або скрипта стартував лише після того, як інший файл було завантажено й розпарсено? Це кандидат для preload.
Якщо запит стартує лише після тривалого DNS/TCP/TLS setup до стороннього origin, це кандидат для preconnect.
Якщо з поточною сторінкою все гаразд, але наступна навігація передбачувано повільна, може допомогти prefetch.
2. Додавайте по одній підказці
Resource hints взаємодіють між собою. Додайте одну, протестуйте її й залишайте лише тоді, коли waterfall покращується, а метрики, видимі користувачам, не регресують.
Для preload стежте, чи підказаний ресурс справді використовується скоро. Chrome може попереджати, коли preloaded ресурс не використано невдовзі після завантаження. Сприймайте це попередження серйозно.
3. Перевірте побічні ефекти пріоритетів
Preload може відтягнути пропускну здатність від CSS, JavaScript або зображень, які важливіші. Preconnect може зайняти слот з’єднання. Prefetch може додати фоновий трафік.
Правильний результат — не «підказаний файл стартує раніше». Правильний результат — «сторінка стає відчутно кращою для користувачів». Дивіться на LCP, INP, CLS і, де можливо, real-user monitoring.
4. Перевірте заголовки й кешування
Підказки можна надсилати в HTML або HTTP Link headers. Headers корисні, коли сервер рано знає, що знадобиться сторінці, але їх складніше побіжно перевіряти. Якщо ви налагоджуєте, чи підказка справді присутня в production, важливі raw headers; це саме така ситуація, яку ми розглядаємо в our guide to debugging redirects and HTTP headers.
Кешування також має значення. Preloading ресурсу з невідповідними credentials, неправильним as або іншими параметрами URL може спричинити дубльовані завантаження. Це один із найпоширеніших способів, коли preload із добрими намірами стає performance bug.
Поширені помилки
Preloading надто великої кількості ресурсів
Якщо все критичне, то критичним не є нічого. Обмежуйте preload ресурсами, потрібними для початкового рендерингу або негайної інтерактивності. Типова сторінка має мати від нуля до трьох preload, а не двадцять.
Використання prefetch для обов’язкових ресурсів
Prefetch має низький пріоритет і є необов’язковим. Не використовуйте його для ресурсів, потрібних поточній сторінці. Якщо сторінці це потрібно зараз, розгляньте preload або нормальне виявлення через HTML.
Preconnecting до кожного стороннього сервісу
Сторінки з великою кількістю third-party часто мають десять або більше зовнішніх origin. Preconnecting до всіх створює шум. Оберіть один-два, які одночасно критичні й передбачувано використовуються.
Ігнорування мобільних умов
Resource hints найцінніші на повільніших з’єднаннях, але там вони й найнебезпечніші. Змарнований prefetch на швидкому desktop-з’єднанні — це похибка округлення. На обмеженому мобільному тарифі — поганий компроміс.
Проста таблиця рішень
| Ситуація | Найкраща підказка | Чому | |---|---:|---| | Критичний шрифт виявляється через CSS | preload | Поточній сторінці він потрібен, виявлення пізнє | | Hero image прихований за CSS або клієнтським рендерингом | preload | Може покращити LCP, якщо зображення стартує пізно | | Ймовірний наступний route після наміру користувача | prefetch | Допомагає майбутній навігації, не блокуючи поточну сторінку | | Критичний сторонній font/API origin | preconnect | Прибирає встановлення з’єднання з критичного шляху | | Можливий, але непевний сторонній origin | dns-prefetch або нічого | Нижча вартість, нижча впевненість | | Зображення нижче першого екрана | нічого | Дозвольте lazy loading і пріоритетам браузера працювати |
Спокійне правило
Resource hints працюють найкраще, коли вони нудні й конкретні. Один шрифт. Одне LCP-зображення. Один важливий сторонній origin. Один імовірний наступний route після наміру.
Вони працюють погано, коли їх використовують як оптимізм: можливо, користувачу це знадобиться, можливо, браузеру варто завантажити те, можливо, більше підказок означає більше швидкості.
Браузери вже агресивно оптимізують. Ваше завдання — не мікроменеджити кожен запит. Ваше завдання — виправити кілька випадків, коли браузеру бракує інформації в потрібний момент.