PurpleSchool — курсы программирования онлайн
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развития
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • Карьерные пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • PurpleSchool — курсы программирования онлайн
    • Сообщество
    • PurpleПлюс
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Оптимизация LCP: как я довёл Web Vitals до 1.5 секунд на реальном проекте

    Оптимизация LCP: как я довёл Web Vitals до 1.5 секунд на реальном проекте

    Аватар автора Оптимизация LCP: как я довёл Web Vitals до 1.5 секунд на реальном проекте

    Антон Ларичев

    Иконка календаря27 марта 2026
    performancehtmlmiddleИконка уровня middle
    Картинка поста Оптимизация LCP: как я довёл Web Vitals до 1.5 секунд на реальном проекте

    Введение

    Оптимизация LCP — одна из ключевых задач при работе с производительностью веб-приложений. Largest Contentful Paint (LCP) показывает, как быстро пользователь видит основной контент страницы, и напрямую влияет на поведенческие факторы и позиции в поиске Google. В этой статье я расскажу, как на реальном проекте довёл показатель LCP с 4.8 до 1.5 секунд, и покажу конкретные приёмы, которые вы можете применить уже сегодня.

    Core Web Vitals — это набор метрик Google для оценки пользовательского опыта. LCP считается «хорошим», если загрузка основного контента происходит за 2.5 секунды или быстрее. Всё, что выше — красная зона, которая бьёт и по SEO, и по конверсии.

    Диагностика: как найти узкие места LCP

    Прежде чем оптимизировать, нужно понять, что именно тормозит. Для этого я использовал три инструмента:

    • Lighthouse в Chrome DevTools — для лабораторных замеров
    • PageSpeed Insights — для полевых данных (CrUX)
    • Web Vitals Extension — для мониторинга в реальном времени

    На моём проекте LCP-элементом оказалось hero-изображение размером 1920x1080 в формате PNG (2.3 МБ). Lighthouse показал LCP = 4.8 секунды на мобильных. Разбивка задержки выглядела так:

    TTFB (Time to First Byte):   1.2 сек
    Загрузка ресурса (изображение): 2.8 сек
    Рендеринг:                     0.8 сек
    

    Стало понятно: основная проблема — размер изображения и отсутствие предзагрузки.

    Оптимизация изображений для LCP

    Первый и самый эффективный шаг — работа с изображениями. Вот что я сделал:

    Переход на современные форматы (WebP и AVIF)

    Конвертация hero-изображения из PNG в WebP сократила размер с 2.3 МБ до 320 КБ — почти в 7 раз. AVIF дал ещё лучший результат: 210 КБ.

    <picture>
      <source srcset="/hero.avif" type="image/avif">
      <source srcset="/hero.webp" type="image/webp">
      <img src="/hero.png" alt="Hero изображение" width="1920" height="1080">
    </picture>
    

    Адаптивные изображения через srcset

    Нет смысла загружать картинку 1920px на мобильном экране шириной 375px. Атрибут srcset решает эту проблему:

    <img
      srcset="
        /hero-480.webp 480w,
        /hero-768.webp 768w,
        /hero-1200.webp 1200w,
        /hero-1920.webp 1920w
      "
      sizes="100vw"
      src="/hero-1920.webp"
      alt="Hero изображение"
      width="1920"
      height="1080"
      fetchpriority="high"
    />
    

    Обратите внимание на fetchpriority="high" — этот атрибут говорит браузеру загружать LCP-изображение с максимальным приоритетом.

    Preload для LCP-элемента

    Браузер не может начать загрузку изображения, пока не распарсит HTML и CSS. Preload позволяет начать загрузку раньше:

    <link
      rel="preload"
      as="image"
      href="/hero-1200.webp"
      type="image/webp"
      fetchpriority="high"
      imagesrcset="/hero-480.webp 480w, /hero-768.webp 768w, /hero-1200.webp 1200w"
      imagesizes="100vw"
    />
    

    Один только preload сократил LCP на 0.6 секунды.

    Как ускорить загрузку основного контента: шрифты и CSS

    Оптимизация шрифтов

    Кастомные шрифты часто блокируют рендеринг. Два ключевых приёма:

    @font-face {
      font-family: 'CustomFont';
      src: url('/fonts/custom.woff2') format('woff2');
      font-display: swap; /* Показываем текст сразу, шрифт подгрузится позже */
      unicode-range: U+0400-04FF, U+0020-007F; /* Только кириллица и латиница */
    }
    

    Preload для основного шрифта:

    <link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossorigin>
    

    Подгрузка только нужного unicode-range вместо полного набора символов сократила размер шрифта с 180 КБ до 45 КБ.

    Удаление блокирующего CSS

    Критический CSS — стили, необходимые для отрисовки первого экрана — я вынес в инлайн:

    <head>
      <!-- Критический CSS инлайн -->
      <style>
        .hero { position: relative; min-height: 60vh; }
        .hero img { width: 100%; height: auto; display: block; }
        /* ... остальные стили первого экрана */
      </style>
      <!-- Некритический CSS загружается асинхронно -->
      <link rel="preload" href="/styles.css" as="style" onload="this.rel='stylesheet'">
    </head>
    

    Серверная оптимизация: снижаем TTFB

    TTFB в 1.2 секунды — это слишком. Вот что помогло:

    Кеширование и CDN

    Подключение CDN (Cloudflare) снизило TTFB с 1.2 до 0.3 секунды для большинства пользователей. Настройка заголовков кеширования:

    # nginx.conf
    location ~* \.(webp|avif|woff2|js|css)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    location / {
        add_header Cache-Control "public, max-age=3600, stale-while-revalidate=86400";
    }
    

    Сжатие Brotli

    Brotli сжимает эффективнее gzip на 15-25%:

    brotli on;
    brotli_types text/html text/css application/javascript application/json image/svg+xml;
    brotli_comp_level 6;
    

    Устранение блокирующих скриптов

    Сторонние скрипты — аналитика, чаты, виджеты — часто блокируют рендеринг. Перенёс их загрузку:

    <!-- Было: блокирующий скрипт -->
    <script src="/analytics.js"></script>
    
    <!-- Стало: отложенная загрузка -->
    <script src="/analytics.js" defer></script>
    
    <!-- Или загрузка после полной отрисовки страницы -->
    <script>
      window.addEventListener('load', () => {
        const script = document.createElement('script');
        script.src = '/analytics.js';
        document.body.appendChild(script);
      });
    </script>
    

    Итоговые результаты оптимизации

    Каждый шаг давал измеримый вклад в улучшение LCP:

    Оптимизация Снижение LCP
    WebP/AVIF + srcset -1.8 сек
    Preload LCP-изображения -0.6 сек
    CDN + кеширование -0.5 сек
    Инлайн критического CSS -0.2 сек
    Оптимизация шрифтов -0.1 сек
    Defer сторонних скриптов -0.1 сек
    Итого 4.8 -> 1.5 сек

    Частые ошибки при оптимизации LCP

    • Lazy load на LCP-элементе. Атрибут loading="lazy" на hero-изображении увеличивает LCP — браузер откладывает загрузку самого важного элемента. Lazy load нужен только для контента ниже первого экрана.
    • Отсутствие width и height у изображений. Без указания размеров браузер не может зарезервировать место, что приводит к сдвигу макета (CLS) и пересчёту рендеринга.
    • Загрузка всех шрифтов на каждой странице. Если на странице используется только один шрифт — не подключайте пять начертаний «на всякий случай».
    • Игнорирование мобильных данных. Lighthouse в DevTools показывает лабораторные данные. Реальные пользователи на 3G будут видеть совсем другую картину — проверяйте полевые данные в PageSpeed Insights.

    Заключение

    Оптимизация LCP — это не магия, а последовательная работа с изображениями, шрифтами, CSS, серверными настройками и сторонними скриптами. Самый большой выигрыш дают современные форматы изображений и preload. Каждый из описанных шагов можно внедрить за день, а результат будет виден сразу в Lighthouse и PageSpeed Insights. Начните с диагностики, определите свой LCP-элемент — и применяйте оптимизации по очереди, замеряя эффект каждого шага.

    Иконка глаза252

    Комментарии

    0

    Постройте личный план изучения Vue.js 3, Vue Router и Pinia до уровня Middle — бесплатно!

    Vue.js 3, Vue Router и Pinia — часть карты развития Frontend

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Angular 21

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Nuxt

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Feature-Sliced Design

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.5
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста Анимации в CSS: transition, @keyframes и View Transitions API
    Иконка аватараАнтон
    Иконка календаря24 марта 2026
    csshtmljavascriptmiddleИконка уровня middle

    Анимации в CSS: transition, @keyframes и View Transitions API

    Анимации в CSS позволяют создавать плавные переходы и сложные эффекты без JavaScript. Разбираем CSS transition, @keyframes и новый View Transitions API с практическими примерами.

    Иконка чипа0
    Иконка глаза204
    Иконка комментариев0
    Картинка поста Как внедрить тесты в проект, где их никогда не было: пошаговая стратегия
    Иконка аватараАнтон
    Иконка календаря14 апреля 2026
    testingjavascripttypescriptmiddleИконка уровня middle

    Как внедрить тесты в проект, где их никогда не было: пошаговая стратегия

    Пошаговая стратегия внедрения тестов в существующий проект: с чего начать тестирование legacy-кода, какие тесты писать первыми и как настроить Vitest для JavaScript и TypeScript.

    Иконка чипа0
    Иконка глаза62
    Иконка комментариев0
    Картинка поста Тестирование API: от unit-тестов до e2e с Playwright и Vitest
    Иконка аватараАнтон
    Иконка календаря13 апреля 2026
    testingnodejstypescriptmiddleИконка уровня middle

    Тестирование API: от unit-тестов до e2e с Playwright и Vitest

    Как выстроить тестирование API на практике: unit-тесты в Vitest, интеграционные проверки с MSW и e2e-сценарии в Playwright. Примеры на TypeScript с полным покрытием.

    Иконка чипа0
    Иконка глаза87
    Иконка комментариев0
    Иконка чипа0