Чому ваш сайт має надсилати менше запитів, а не менші запити
Крихітні файли не безкоштовні. Сучасний HTTP зменшив накладні витрати на запити, але не зробив їх неважливими.
Зміст
- Зручний міф про «просто зробіть кожен файл меншим»
- Запити — це не лише байти
- «Але HTTP/2 це виправив» — здебільшого ні
- Waterfall — місце, де живе правда
- Менші файли все ще важливі — просто не однаково
- Приховані витрати багатьох малих файлів
- 1. Пізнє виявлення
- 2. Накладні витрати заголовків
- 3. Переривання головного потоку
- 4. Складність кешу
- Bundling повернувся, але з розсудливістю
- До сторонніх запитів варто ставитися з особливою підозрою
- Практичний чекліст для зменшення запитів
- Видаліть
- Об’єднуйте обдумано
- Відкладайте
- Кешуйте правильно
- Виміряйте повторно
- Як виглядає добре
Зручний міф про «просто зробіть кожен файл меншим»
Упродовж років поради щодо продуктивності вебу звучали просто: стискайте все, мінімізуйте все, робіть кожен ресурс меншим.
Ця порада й досі загалом правильна. Скрипт на 40 KB зазвичай кращий за скрипт на 400 KB. Оптимізоване зображення краще за сирий експорт. Brotli, AVIF, мінімізація CSS, tree shaking і підмножини шрифтів — усе це має значення.
Але на багатьох продакшн-сайтах більша проблема вже не в одному завеликому файлі. Вона в кількості речей, які браузер має запросити, перш ніж сторінка почне відчуватися придатною до використання.
Сторінка може виглядати дисципліновано за розмірами файлів і все одно бути повільною, бо вона надсилає 120 запитів: фрагменти CSS, чанки JavaScript, сторонні теги, файли шрифтів, пікселі відстеження, спрайти іконок, JSON-ендпоїнти, preloads, аналітичні beacons і повторні перевірки кешу. Кожен із них може бути «малим». Разом вони створюють довгий, крихкий waterfall.
Практичне правило таке: щойно окремі ресурси достатньо стиснуті, зменшення кількості запитів часто покращує досвід користувача більше, ніж економія кількох кілобайтів у кожному файлі.
Запити — це не лише байти
Мережевий запит — це не лише передавання даних. Це послідовність роботи.
Браузер має знайти ресурс, вирішити, коли його завантажувати, розпланувати його відносно інших ресурсів, надіслати заголовки, дочекатися сервера, отримати заголовки, розібрати відповідь, часто розпакувати її, а потім зробити з нею щось корисне.
Це «щось корисне» може бути дорогим. Файл JavaScript потрібно розібрати, скомпілювати й виконати. Файл CSS може блокувати рендеринг. Файл шрифту може затримати читабельний текст або спричинити зсуви макета. Зображення може вплинути на елемент Largest Contentful Paint. Сторонній скрипт може принести власний ланцюжок залежностей.
Ось чому кількість запитів досі має значення, навіть коли файли малі. Скрипт на 3 KB може бути гіршим за зображення на 30 KB, якщо він блокує рендеринг, приходить пізно й виконується в головному потоці в невдалий момент.
Якщо ви читаєте звіт Lighthouse і відчуваєте, що вас карають десятками окремих попереджень, почніть із waterfall запитів, а не з окремих оцінок. У нас є практичний розбір у матеріалі про те, як читати звіт Lighthouse без паніки, але коротка версія така: знайдіть, що блокує перший рендер і що затримує основний вміст.
«Але HTTP/2 це виправив» — здебільшого ні
HTTP/2 і HTTP/3 змінили економіку запитів. Вони запровадили мультиплексування, стиснення заголовків і кращу поведінку з’єднань. Простими словами, браузери стали значно краще надсилати кілька запитів через меншу кількість з’єднань.
Це було справжнім покращенням. Воно також поклало край деяким старим звичкам, як-от екстремальні CSS-спрайти та гігантські склеєні бандли, створені лише для обходу обмежень на кількість з’єднань.
Але HTTP/2 не зробив запити безкоштовними.
Мультиплексування допомагає, коли багато ресурсів спільно використовують одне з’єднання, але браузер усе одно має розставляти для них пріоритети. Сервери все одно мають відповідати. Клієнт усе одно має обробляти кожну відповідь. Перевантаження мережі, втрата пакетів, TLS negotiation, DNS lookup, промахи кешу й тиск на головний потік нікуди не зникли.
HTTP/3 покращує деякі аспекти транспорту, особливо навколо міграції з’єднань і head-of-line blocking на транспортному рівні. Він не усуває вартість виявлення, планування, завантаження, розбору й виконання ресурсів.
Тож сучасна мета — не «зібрати все в один величезний файл». Вона така: «надсилати менше критичних запитів і зробити решту запитів навмисними».
Waterfall — місце, де живе правда
Проблеми продуктивності рідко заявляють про себе однією метрикою. Вони проявляються формою.
Відкрийте мережеву панель браузера й подивіться на перші кілька секунд. Запитайте:
- Скільки запитів стартує до появи основного вмісту?
- Які запити блокують рендеринг?
- Чи важливі ресурси виявляються запізно?
- Чи сторонні скрипти конкурують із власними CSS, шрифтами або зображеннями?
- Чи багато файлів повертають відповіді 304 замість того, щоб віддаватися безпосередньо з кешу?
- Чи іконки, шрифти або фрагменти UI розбиті на більше файлів, ніж сторінці потрібно?
Швидка сторінка зазвичай має нудний ранній waterfall. Невелика кількість критичних ресурсів приходить рано. Некритичні ресурси чекають. Сторонні скрипти відкладені, обмежені або видалені. Браузер не змушений жонглювати двадцятьма пріоритетами, перш ніж зможе намалювати сторінку.
Повільна сторінка часто має нервовий waterfall: багато малих файлів, багато origin і багато пізніх виявлень.
Менші файли все ще важливі — просто не однаково
Це не аргумент проти стиснення чи оптимізації. Це аргумент проти оптимізації байтів із ігноруванням координації.
Менші файли найважливіші тоді, коли ресурс великий, блокує рендеринг або є частиною шляху до основного вмісту. Наприклад:
- Hero-зображення має бути правильно розмірене й закодоване.
- CSS, що блокує рендеринг, має бути легким.
- JavaScript, потрібний для першої взаємодії, має бути мінімальним.
- Шрифти мають бути зібрані в підмножини, стиснуті й обмежені тими насиченостями, які справді використовуються.
Шрифти — типовий приклад. Команди часто зациклюються на тому, чи файл шрифту має 24 KB або 31 KB, водночас відправляючи шість насиченостей, два стилі й кілька гарнітур. Краще рішення — не зекономити 7 KB в одному файлі. Краще рішення — надсилати менше файлів шрифтів. Якщо типографіка є частиною вашої роботи над продуктивністю, вебшрифти все ще залишаються одним із найпростіших виграшів на більшості сайтів.
Із зображеннями та сама схема. AVIF або WebP можуть суттєво заощадити байти, але надсилати десять декоративних зображень вище лінії згину — усе ще поганий план. Так, обирайте кращі формати, але також ставте питання, чи кожне зображення взагалі потрібно запитувати. Для рішень щодо форматів наш гід про те, коли AVIF перемагає WebP, а коли ні, добре доповнює цю роботу зі зменшення кількості запитів.
Приховані витрати багатьох малих файлів
Багато малих запитів схильні створювати проблеми, яких не видно, якщо дивитися лише на загальний обсяг переданих байтів.
1. Пізнє виявлення
Браузери не можуть запросити те, чого ще не виявили. Файл CSS може посилатися на шрифт. Скрипт може імпортувати інший скрипт. Компонент може запросити JSON після hydration. Кожна залежність створює ще один крок у ланцюжку.
Що глибший ланцюжок, то пізніше починається важлива робота.
2. Накладні витрати заголовків
Кожен запит і відповідь містять заголовки. Стиснення заголовків допомагає, особливо через HTTP/2 і HTTP/3, але воно не усуває накладні витрати. Cookies можуть значно погіршити ситуацію. Якщо ваш сайт надсилає великі cookies із кожним запитом, крихітні ресурси на практиці стають менш крихітними.
Це одна з причин, чому статичні ресурси часто мають жити на шляхах або доменах без cookies, і чому заголовки кешування заслуговують на увагу. Якщо заголовки в продакшні поводяться дивно, налагодження редиректів і HTTP-заголовків зазвичай швидше за здогадки.
3. Переривання головного потоку
Багато чанків JavaScript можуть створювати повторювану роботу з розбору й виконання. Навіть якщо кожен чанк малий, браузер може постійно зупинятися, щоб оцінити код. Це може погіршити Interaction to Next Paint і зробити сторінку смиканою на відчуття.
Користувачу байдуже, що кожен файл був малим. Йому важливо, що натискання на меню зайняло 600 мілісекунд.
4. Складність кешу
Розбиття ресурсів може покращити кешування, якщо робити це обережно. Стабільний vendor bundle і змінний app bundle можуть бути вдалим поділом.
Але надмірне дроблення на чанки може мати зворотний ефект. Більше файлів означає більше звернень до кешу, більше можливостей для повторної перевірки, більше координації версій і більше способів випадково інвалідовувати ресурси, які не мали змінюватися.
Bundling повернувся, але з розсудливістю
Перша ера вебпродуктивності любила bundling, бо браузери мали жорсткі обмеження на кількість з’єднань. Потім з’явився HTTP/2, і багато команд різко хитнулися в бік агресивного code splitting. Частина цього була корисною. Частина перетворилася на забобон.
Розумна середина — route-aware bundling.
Для типового маркетингового або контентного сайту:
- Inline або завантажуйте лише CSS, потрібний для початкового рендерингу.
- Тримайте глобальний JavaScript малим.
- Уникайте розбиття крихітних модулів на окремі мережеві запити.
- Відкладайте інтерактивні функції, які не потрібні негайно.
- Видаляйте сторонні скрипти, що не виправдовують своєї вартості.
Для застосунку:
- Розбивайте за маршрутом або великою функцією, а не за кожним компонентом.
- Тримайте спільні залежності стабільними й придатними до кешування.
- Preload робіть лише для ресурсів, які точно знадобляться незабаром.
- Уникайте завантаження коду admin, dashboard, editor або experiment на публічних сторінках.
- Вимірюйте вартість взаємодії, а не лише розмір bundle.
Bundling не є автоматично добрим. Code splitting не є автоматично добрим. Корисне питання таке: чи допомагає цей поділ браузеру швидше доставити наступний значущий досвід користувача?
До сторонніх запитів варто ставитися з особливою підозрою
Власні запити принаймні під вашим контролем. Сторонні запити часто повільніші, менш передбачувані й дорожчі, ніж здаються.
Один tag manager може запускати аналітику, рекламу, heatmaps, chat widgets, A/B testing, consent tools і скрипти персоналізації. Кожен vendor може принести більше запитів. Деякі виконуватимуться рано. Деякі блокуватимуть головний потік. Деякі змінюватимуться без вашого release process.
Найкраща оптимізація стороннього коду — видалення. Друга найкраща — відкладання.
Перш ніж додати сторонній скрипт, запитайте:
- Чи це має завантажитися до того, як користувач побачить сторінку?
- Чи це має завантажуватися на кожній сторінці?
- Чи може це завантажитися після consent, взаємодії або idle time?
- Хто володіє цим усередині компанії?
- Яка метрика доводить, що це варте своєї вартості для продуктивності?
Саме тут продуктивність стає управлінням. Хтось має мати право сказати «ні».
Практичний чекліст для зменшення запитів
Почніть зі сторінок, які мають найбільше значення: головна, сторінка цін, сторінка продукту, checkout, signup або топові landing pages. Потім пройдіться waterfall.
Видаліть
- Видаліть невикористані JavaScript і CSS.
- Видаліть старі експерименти, покинуті пікселі й дубльовану аналітику.
- Відмовтеся від невикористаних насиченостей шрифтів і бібліотек іконок.
- Замініть декоративні зображення на CSS там, де це доречно.
Об’єднуйте обдумано
- Об’єднуйте крихітні модулі JavaScript, які завжди завантажуються разом.
- Об’єднуйте малі файли CSS, що блокують той самий шлях рендерингу.
- Використовуйте SVG-спрайти або inline SVG для повторюваних іконок, коли це зменшує запити без шкоди для підтримуваності.
Відкладайте
- Lazy-load зображення нижче лінії згину.
- Відкладайте некритичні скрипти до моменту після first paint або взаємодії користувача.
- Завантажуйте коментарі, embeds, мапи, чат і відеоплеєри лише тоді, коли вони потрібні.
Кешуйте правильно
- Використовуйте довготривале кешування для версіонованих статичних ресурсів.
- Уникайте непотрібної повторної перевірки файлів, які рідко змінюються.
- Тримайте HTML свіжим, але дозволяйте hashed assets залишатися в кеші.
Виміряйте повторно
Після кожної зміни знову перевіряйте waterfall. Мета — не ідеальна оцінка. Мета — менше критичних запитів, раніший корисний рендеринг і менше порушень у головному потоці.
Як виглядає добре
Здорова сторінка не обов’язково має найменшу можливу кількість запитів. Вона має малий, продуманий критичний шлях.
Браузер отримує HTML, essential CSS, основне зображення вмісту, якщо воно є, можливо, невеликий скрипт, потрібний для навігації або взаємодії вище лінії згину, і мінімальний набір шрифтів, необхідний, щоб текст був читабельним. Усе інше чекає своєї черги.
У цьому різниця між сторінкою, яка просто оптимізована, і сторінкою, яка відчувається швидкою.
Зменшувати файли все ще варто. Але якщо сайт уже достатньо стиснутий, наступний виграш у продуктивності зазвичай не ще 2 KB, зекономлені з bundle. Це на один блокувальний запит менше, на один файл шрифту менше, на один сторонній скрипт менше, на один ланцюжок залежностей менше.
Менша кількість запитів спрощує роботу браузера. Просте частіше буває швидким, ніж нам хочеться визнавати.