Каждая лишняя секунда загрузки обходится дорого. Google ещё в 2017 году зафиксировал: при увеличении времени загрузки с 1 до 3 секунд вероятность того, что пользователь уйдёт, вырастает на 32%. При 5 секундах — уже на 90%. С тех пор люди стали только нетерпеливее.

Если у вас сайт грузится дольше 3 секунд — вы теряете клиентов. Не абстрактно, а буквально: они закрывают вкладку и идут к конкуренту.

Разберём, что реально влияет на скорость и что можно сделать без переписывания всего с нуля.

Сначала измерьте — потом оптимизируйте

Без замеров оптимизация — это стрельба вслепую. Два инструмента, которые нужны всегда:

Google PageSpeed Insights (pagespeed.web.dev) — показывает Core Web Vitals: LCP, CLS, INP. Это метрики, на которые смотрит Google при ранжировании. Бесплатно, работает онлайн, ничего устанавливать не надо.

WebPageTest (webpagetest.org) — более детальный анализ. Показывает водопад запросов (waterfall), время до первого байта (TTFB), можно эмулировать разные регионы и типы соединений.

Что смотреть в первую очередь:

  • LCP (Largest Contentful Paint) — когда загружается главный контент страницы. Норма: до 2,5 секунды.
  • TTFB (Time to First Byte) — как быстро сервер отвечает. Норма: до 800 мс. Если больше — проблема на уровне сервера или хостинга.
  • Размер страницы — сколько весит всё, что скачивает браузер. Средний сайт в 2026 году весит около 2,5 МБ. Это много.

После замера будет понятно, где узкое место: картинки, JS, сервер или что-то ещё.

Изображения — главный пожиратель скорости

В большинстве случаев именно картинки составляют 60–80% веса страницы. Здесь самый быстрый выигрыш.

Используйте современные форматы. WebP весит в среднем на 25–35% меньше JPEG при том же качестве. AVIF — ещё на 20% легче WebP, но поддерживается не всеми браузерами. Безопасная стратегия — отдавать WebP с фолбэком на JPEG через тег <picture>:

<picture>
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="Описание">
</picture>

Сжимайте изображения перед загрузкой. Squoosh (squoosh.app) — бесплатный инструмент от Google прямо в браузере. Можно сжать фото с 800 КБ до 120 КБ без заметной потери качества. Для автоматизации на сервере — ImageMagick или Sharp (Node.js).

Используйте атрибут loading="lazy". Браузер загрузит изображения только когда они появятся в зоне видимости. Одна строка кода, работает во всех современных браузерах:

<img src="photo.jpg" loading="lazy" alt="Описание">

Задавайте размеры изображений. Если не указать width и height, браузер не знает, сколько места зарезервировать, и страница «прыгает» при загрузке (это влияет на CLS). Всегда прописывайте размеры явно.

Не загружайте изображения больше, чем нужно. Если на мобильном экране картинка отображается в 400px, незачем грузить 1600px. Используйте атрибут srcset:

<img
  src="photo-800.jpg"
  srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
  sizes="(max-width: 600px) 400px, 800px"
  alt="Описание"
>

Кэширование — чтобы не грузить одно и то же дважды

Когда пользователь заходит на сайт повторно, браузер может взять файлы из кэша, а не скачивать снова. Настраивается через HTTP-заголовки на сервере.

Для статичных файлов (CSS, JS, картинки) ставьте долгий кэш — год и более. Для HTML — короткий или вообще без кэша, чтобы обновления сразу доходили до пользователей.

Пример для Nginx:

location ~* \.(jpg|jpeg|png|gif|webp|css|js|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

immutable говорит браузеру: «этот файл никогда не изменится, не проверяй его даже при принудительном обновлении». Это работает только если вы используете хэши в именах файлов (например, main.a3f9c2.js) — стандартная практика при сборке через Webpack, Vite, Parcel.

Кэширование на сервере. Если сайт на WordPress или другой CMS — подключите серверное кэширование. WP Super Cache или W3 Total Cache генерируют статичные HTML-файлы вместо того, чтобы каждый раз запрашивать базу данных. На высоконагруженных сайтах это снижает TTFB с 500–800 мс до 50–100 мс.

Минификация и сжатие кода

Минификация — удаление пробелов, комментариев, переименование переменных. CSS с 150 КБ после минификации может стать 90 КБ. Для JS экономия ещё больше. Если используете сборщик (Vite, Webpack) — минификация включается одной строкой в конфиге. В WordPress — плагины Autoptimize или LiteSpeed Cache.

Gzip и Brotli — сжатие на уровне передачи данных. Сервер сжимает файл перед отправкой, браузер распаковывает. Brotli эффективнее Gzip примерно на 15–25%. Включается в Nginx:

gzip on;
gzip_types text/css application/javascript application/json;

brotli on;
brotli_types text/css application/javascript application/json;

Проверить, работает ли сжатие: в DevTools на вкладке Network смотрите колонки Size и Transferred. Если Transferred значительно меньше Size — сжатие работает.

Оптимизация JavaScript — самое больное место

JS блокирует рендеринг страницы. Пока скрипт не загрузился и не выполнился, браузер не отрисует то, что идёт после него.

Атрибуты async и defer. По умолчанию скрипт в <head> останавливает парсинг HTML. async загружает скрипт параллельно и выполняет сразу после загрузки. defer — загружает параллельно, но выполняет только после парсинга всего HTML. Для большинства скриптов подходит defer:

<script src="analytics.js" defer></script>

Code splitting. Не грузите весь JS сразу. Код, который нужен только на странице корзины, не нужен на главной. Webpack и Vite поддерживают динамический импорт из коробки:

// Грузим модуль только когда он нужен
const { initCart } = await import('./cart.js');

Tree shaking. Если подключаете библиотеку типа Lodash ради одной функции — подключайте только её, а не всю библиотеку:

// Плохо — загружается весь Lodash (~70 КБ)
import _ from 'lodash';

// Хорошо — только нужная функция (~1 КБ)
import debounce from 'lodash/debounce';

Проверьте, что вы вообще грузите. Инструмент bundlephobia.com показывает вес любой npm-пакета. Иногда оказывается, что ради небольшой задачи подключена библиотека на 200 КБ, а нативный JS справился бы тремя строками.

CDN — когда сервер далеко от пользователя

CDN (Content Delivery Network) — сеть серверов по всему миру. Пользователь из Владивостока получает файлы не с сервера в Москве, а с ближайшей точки CDN — например, из Хабаровска. Скорость передачи данных физически ограничена расстоянием.

Cloudflare — самый распространённый вариант, есть бесплатный тариф. Помимо CDN даёт защиту от DDoS и автоматическую минификацию. Подключается на уровне DNS — менять хостинг не нужно.

Для статичных файлов (картинки, видео, шрифты) CDN особенно эффективен. Динамический контент — сложнее, но тоже решаемо.

Шрифты — незаметный, но важный фактор

Кастомные шрифты могут существенно тормозить отображение текста.

Используйте font-display: swap. По умолчанию браузер ждёт загрузки шрифта перед отображением текста (FOIT — Flash of Invisible Text). swap говорит: покажи системный шрифт сразу, потом замени на кастомный:

@font-face {
  font-family: 'MyFont';
  src: url('font.woff2') format('woff2');
  font-display: swap;
}

Загружайте только нужные начертания. Если используете только Regular и Bold — не подключайте Light, Medium, SemiBold, Black. Каждое начертание — отдельный файл.

Используйте формат WOFF2. Он весит на 30% меньше WOFF и поддерживается всеми современными браузерами.

Если используете Google Fonts — размещайте шрифты на своём сервере. Внешний запрос к fonts.googleapis.com — это лишний DNS-lookup и время ожидания. Инструмент google-webfonts-helper помогает скачать нужные шрифты.

Критический CSS и предзагрузка ресурсов

Critical CSS — инлайнинг стилей, необходимых для отображения верхней части страницы (above the fold), прямо в HTML. Браузер не ждёт загрузки CSS-файла и сразу рисует контент. Остальные стили подгружаются асинхронно. Инструмент Critical (npm) автоматизирует этот процесс.

Preload для критичных ресурсов. Если знаете, что определённый ресурс точно понадобится — сообщите браузеру заранее:

<link rel="preload" href="hero.webp" as="image">
<link rel="preload" href="main.woff2" as="font" type="font/woff2" crossorigin>

DNS prefetch и preconnect для внешних ресурсов:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://analytics.example.com">

База данных и серверная часть

Если TTFB высокий (больше 800 мс) — проблема не в клиентской части. Смотрите на сервер.

Индексы в базе данных. Медленные запросы без индексов — частая причина тормозов. В MySQL/PostgreSQL используйте EXPLAIN для анализа запросов. Добавление индекса на нужное поле может ускорить запрос с 2 секунд до 10 миллисекунд.

OPcache для PHP. Кэширует скомпилированные PHP-скрипты в памяти. Включается одной строкой в php.ini и ускоряет работу PHP-приложений в 5–10 раз.

Redis или Memcached для кэша. Результаты тяжёлых запросов к БД сохраняйте в памяти. Повторный запрос отдаёт данные за микросекунды вместо десятков миллисекунд.

Проверьте сторонние скрипты

Аналитика, чаты, пиксели соцсетей, виджеты — каждый сторонний скрипт делает отдельный запрос к внешнему серверу и выполняет свой JS. На некоторых сайтах сторонние скрипты составляют половину веса страницы.

Проверьте в WebPageTest, какие домены запрашиваются при загрузке. Уберите всё лишнее. Оставшееся — загружайте с async или defer, чтобы не блокировать основной поток.

Если используете Google Analytics 4 — можно настроить серверную аналитику, чтобы не грузить JS на клиенте вообще.

Что делать дальше

Оптимизация скорости — не разовая задача. Сайт обрастает новыми скриптами, плагинами, тяжёлыми картинками. Имеет смысл проверять PageSpeed раз в квартал.

Порядок действий, если хотите начать прямо сейчас:

  1. Запустите PageSpeed Insights и посмотрите, что именно тормозит.
  2. Переведите картинки в WebP, поставьте loading="lazy".
  3. Включите Gzip/Brotli и кэширование на сервере.
  4. Подключите Cloudflare (бесплатно).
  5. Уберите неиспользуемые сторонние скрипты.

Эти пять шагов в большинстве случаев дают ощутимый результат без переписывания кода.

Если сайт исторически нагроможден — иногда проще сделать его заново, чем чинить. В REEXY корпоративный сайт начинается от 15 000 ₽, и в эту стоимость уже входит оптимизация под Core Web Vitals. Быстрый сайт с нуля часто обходится дешевле, чем долгая реанимация старого.