Веб-разработка

Производительность фронтенда

Исследование Google: каждые 100мс улучшения скорости загрузки = +1% конверсии. Amazon: задержка 100мс = -1% выручки. Pinterest: сокращение времени загрузки на 40% = +15% регистраций. Производительность фронтенда - не техническая метрика, это бизнес-показатель.

  • **Google** использует Core Web Vitals как ranking signal с 2021 года - медленные сайты теряют позиции в поиске
  • **Shopify** сообщил о 35% улучшении конверсии после перехода на статически генерируемые страницы с агрессивным кешированием
  • **Twitter Lite** с code splitting и Service Worker: 30% снижение bounce rate на медленных сетях в развивающихся рынках

Core Web Vitals: LCP, CLS, INP

Google измеряет «качество пользовательского опыта» тремя метриками, которые влияют на SEO-ранжирование. **Core Web Vitals** - не абстрактные числа: каждая метрика измеряет конкретный раздражающий пользователя сценарий.

**LCP (Largest Contentful Paint)** - когда виден главный контент (изображение, заголовок). Хорошо: до 2.5с. **CLS (Cumulative Layout Shift)** - насколько контент «прыгает» при загрузке. Хорошо: < 0.1. **INP (Interaction to Next Paint)** - задержка между кликом пользователя и обновлением UI. Хорошо: < 200мс.

**Инструменты:** Chrome DevTools (Lighthouse), PageSpeed Insights, Web Vitals extension. Важно: Lab data (Lighthouse) ≠ Field data (реальные пользователи). Google Search Console показывает реальный CWV по вашему сайту.

Изображение на странице прыгает вниз когда загружается баннер выше. Какой Core Web Vital нарушается?

Lazy Loading и Intersection Observer

Страница загружает 30 изображений, из которых пользователь видит только первые 3. Остальные 27 потребляют bandwidth и замедляют загрузку - зря. **Lazy Loading** откладывает загрузку ресурсов до момента, когда они нужны: изображений - до появления в viewport, компонентов - до первого использования.

**Intersection Observer API** - нативный способ отслеживать появление элемента во viewport. Раньше это делали через `scroll` event + `getBoundingClientRect()` - дорого (layout thrashing). Intersection Observer работает асинхронно, не блокирует main thread.

**LCP изображение не должно быть lazy!** Hero изображение вверху страницы - это часто LCP элемент. Если добавить `loading="lazy"` - браузер откладывает его загрузку и LCP растёт. Правило: `loading="lazy"` только для изображений ниже fold.

Почему Intersection Observer лучше scroll event для lazy loading?

Code Splitting и dynamic import

Webpack собирает весь JS в один bundle. 2MB JavaScript грузится, парсится и выполняется даже для пользователей, которые зашли только на главную страницу и никогда не откроют настройки. **Code Splitting** разбивает bundle на чанки, которые загружаются только когда нужны.

**Dynamic import** - ключевой инструмент: `import()` возвращает Promise и является точкой разрыва бандла. Webpack/Vite автоматически выносят динамически импортируемый модуль в отдельный чанк. Route-based splitting в Next.js делает это автоматически для каждой страницы.

**Оптимальный размер чанка:** 50-150KB после gzip для первоначально загружаемых чанков. Слишком много мелких чанков = много HTTP запросов (при HTTP/1.1). Слишком крупные = долгий parse. HTTP/2 multiplexing снижает стоимость дополнительных запросов.

Пользователь открывает главную страницу. Модальное окно настроек открывается в 5% случаев. Code splitting для настроек:

HTTP Caching и Service Workers

Лучший сетевой запрос - тот, которого нет. **HTTP кеширование** позволяет браузеру повторно использовать ранее загруженные ресурсы. Правильно настроенный кеш - это разница между «страница загружается за 3 секунды» и «страница мгновенная для повторных посещений».

**Service Worker** - это прокси-сервер в браузере: перехватывает сетевые запросы и может вернуть ответ из кеша. В отличие от HTTP кеша (только GET, управляется сервером), Service Worker может кешировать POST, динамически выбирать стратегию, работать офлайн.

**Cache busting:** при деплое нового кода старые файлы в кеше браузера остаются. Решение - включать contenthash в имя файла (`main.a1b2c3.js`). Webpack/Vite делают это автоматически. HTML-документ не кешируется жёстко - он всегда ссылается на актуальные hash-имена ассетов.

100% score в Lighthouse означает отличный пользовательский опыт в реальности.

Lighthouse - lab measurement в идеальных условиях. Реальные Core Web Vitals от Chrome User Experience Report (CrUX) отличаются: медленные устройства, нестабильный мобильный интернет.

Lighthouse запускается на мощном ноутбуке с быстрым интернетом. P75 реальных пользователей - совсем другие условия. Оптимизируйте по Field Data из Search Console.

JS bundle деплоится с именем `main.js` (без hash). При деплое нового кода пользователи получат:

Производительность фронтенда

  • CWV: LCP < 2.5с (главный контент), CLS < 0.1 (стабильность), INP < 200мс (отклик) - влияют на SEO
  • Lazy loading: loading='lazy' для below-fold изображений; Intersection Observer для кастомной логики; hero изображение НЕ lazy
  • Code splitting: React.lazy + dynamic import выносит код в отдельный chunk; загружается только при использовании
  • HTTP кеш: immutable assets с contenthash кешируются вечно; HTML no-cache; Service Worker для offline + сложных стратегий

Связанные темы

Производительность фронтенда тесно связана с рендерингом и сетевым стеком:

  • SSR и SSG: Next.js — Streaming SSR улучшает LCP и TTFB напрямую
  • HTTP и CDN — CDN + правильный Cache-Control - основа быстрой доставки ассетов
  • Progressive Web Apps — Service Worker - основа PWA offline-возможностей

Вопросы для размышления

  • Как определить приоритет оптимизаций - с чего начать: LCP, CLS или INP?
  • При каких обстоятельствах aggressive caching может навредить пользователям и как защититься?
  • Чем отличается оптимизация для первого посещения и для повторных - и нужно ли приоритизировать одно над другим?

Связанные уроки

  • db-09-indexes-btree
Производительность фронтенда

0

1

Войти