Время менять шапки: ускорение мобильной поисковой выдачи Циан

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Однажды мы заметили, что поисковая выдача в мобильной версии Циан замедлилась: плохо работала на стороне браузера, грузилось много ресурсов, приложение долго открывалось. Естественно, это не радовало пользователей и сказывалось на метриках. В мае 2021-го Google анонсировал изменения: с августа он станет учитывать метрики Core Web Vitals в ранжировании поисковой выдачи. Мы стали искать, в чём может быть наша проблема. В этой статье расскажем, где же проблема крылась, и как мы её решили.

Core Web Vitals (CWV)

Google предложил метрики для определения качества страниц: FID, LCP и CLS. Дословно Core Web Vitals — это основные интернет-показатели. Каждый из этих показателей представляет собой отчётливый аспект пользовательского опыта. На текущий момент основными показателями являются загрузка, интерактивность, визуальная стабильность.

FID — First Input Delay

Время реакции страницы на первое действие пользователя (при загрузке). В нашем случае это время между тем, как пользователь начал листать галерею, и тем, как на странице что-то изменилось (хотя бы появилась крутилка), или тем, как всё пропало с экрана и началась загрузка новой страницы.

LCP — Largest Contentful Paint

Время от запроса пользователя до окончания рендеринга самого большого элемента в видимой части страницы. Да, важно отрисовать именно самый большой элемент, а остальное потихоньку догрузить. Для нас самый большой элемент — это список объектов недвижимости, но в иных случаях им может быть текстовый блок, видео или баннер. 

CLS — Cumulative Layout Shift

Совокупное смещение макета. Эта метрика чуть хитрее, поскольку состоит из произведения двух параметров: доли неожиданно смещаемых элементов относительно видимой области и расстояния, на которое элементы сместились. В настоящее время учитываются смещения с 1-й по 5-ю секунду после начала отрисовки. То есть если <div /> схлопнуть после начала 6-й секунды, то внезапно CLS примерно с 0,2499 упадёт до 0, если другие элементы останутся на своих местах. (Подробнее показатель описан в этой статье.)

Самодиагностика

Промышленное решение

У нас хороший CLS, прекрасный FID, и подводил только LCP. Мы знаем это благодаря тому, что у нас есть единый отлаженный механизм мониторинга наших сервисов через Grafana. Но пришлось его научить показывать CWV-метрики. С помощью пакета web-vitals мы стали накапливать гуглометрики с реальных пользователей. Затем настроили удобные графики и начали отслеживать динамику. 

Работать с web-vitals оказалось комфортно. Для него не обязательно использовать выделенные хранилища и Grafana (у нас всё это просто уже было настроено и стандартизировано). Метрики можно писать прямо в Google Analytics, там тоже есть графики, разрезы и динамика. Рекомендуем, тем более есть инструкция.

Пока данные накапливались, мы прогнали ключевые страницы через аналитические сервисы. Нам понравились Google Search Console, WebPageTest и Lighthouse. Мы в основном использовали последний, но хороших слов заслуживают все.

Коротко об этом под катом

Google Search Console 

Это возможность посмотреть на сайт глазами Google. Данные собираются непосредственно с пользователей Google Chrome. Google Search Console разделяет метрики мобильной и десктопной версий сайта и позволяет просматривать состояние по каждому из основных интернет-показателей постранично.

Для доступа к сервису необходимо подтверждение владения доменом, поэтому посмотреть, как там у других, или оценить локальную версию (до прода) не получится.

WebPageTest

Бесплатный мощный инструмент для анализа производительности веб-страниц. Его основные преимущества:

  1. Тонкая настройка эмуляций, которая позволяет в лабораторных условиях воспроизводить загрузку страниц на разных скоростях.

  2. Внутри используется Lighthouse с открытым кодом для улучшения качества страниц.

  3. Можно делать тесты с разных локаций.

  4. Мультибраузерность.

  5. Бесплатность.

  6. А ещё можно развернуть свой инстанс.

Lighthouse

Инструмент для аудита конкретных страниц:

  1. Анализирует данные из navigator.performance;

  2. Анализирует загрузку ресурсов и ответы API;

  3. Внутри себя имеет набор разных алгоритмов, которые вычисляют метрики вроде TTI;

  4. Формирует человекопонятный отчёт с рекомендациями к работе.

Ситуация нас не удивила:

  • CLS — прекрасен, у нас очень чёткая сетка и для мобильной, и для адаптивной версии. Впрочем, мы тоже нашли, что улучшить, но об этом дальше.

  • FID — от «хорошо» до «терпимо», на самом деле этот параметр не так просто сломать.

  • LCP — будем чинить.

Минутка занимательной арифметики

С 29 марта по 4 апреля 2 471 156 загрузок нашей мобильной поисковой выдачи и карточек объявления заняли как минимум на 1 секунду больше, чем должны были по Core Web Vitals. А это уже 28 суток. Целый февраль!

Итак, мы подтвердили очевидное с цифрами в руках. Теперь пора решать проблему.

Берём Lighthouse, настраиваем тесты, запускаем.

Результат первого прогона
Результат первого прогона

Внезапно наибольшей проблемой оказывается JavaScript.

Проблема оказалась комплексной. Часть была в коде, часть — в окружении.

Проблемы и решения вне кода

CDN

У нас есть CDN — это географически распределённые хранилища. Когда вы открываете сайт Циан, вам в браузер загружается не только базовый HTML, но ещё скрипты и картинки. 

Мы обнаружили, что в первый раз CDN работал прекрасно. А во второй раз нашлись проблемы с заголовками кэширования. То есть всё то, что мы выиграли за счёт географии в момент, когда пользователю отправлялись скрипты при первом запросе, превращалось в тыкву при ответе или при повторном запросе. То, что уже лежало на устройстве пользователя, закачивалось ему снова из топологически близкого хранилища.

Починить это оказалось проще, чем обнаружить. Мы с девопсами договорились мониторить проблемы с кэшированием в будущем.

GTM — Google Tag Manager

GTM — это удобный инструмент для подключения сторонних аналитических скриптов. Идея прекрасна: разработчик один раз внедряет GTM на страницу, и всё. Дальше его работа заканчивается, добавить или удалить внешний скрипт может любой пользователь, у которого есть права. 

Скрипты для аналитики сейчас бывают весьма продвинутыми. Плюс они стремятся начинать работу как можно раньше, чтобы собрать и передать какие-то данные до того, как пользователь закроет страницу. В итоге до четверти скриптовой нагрузки внезапно пришлось на аналитику.

Нам понадобилось время на то, чтобы аналитики вычистили неиспользуемое и дубли. В дальнейшем мы договорились о процедуре подключения новых инструментов через ревью отдела веб-разработки. Также задумались о том, чтобы сделать A/B-подключение, если скриптов понадобится много. Это поможет сделать так, чтобы на часть пользователей приходилась только часть скриптов.

Проблемы и решения в коде

Наш сайт — полностью динамический. Любая страница собирается React’ом от и до. При этом большая часть страниц отдаётся в основном как HTML. Это старая добрая магия SSR — Server Side Rendering.

В чём плюсы:

  • поисковые роботы получают привычное им чтиво и прекрасно всё индексируют;

  • нагрузка ложится приличной частью на наши сервера, а не на устройство пользователя;

  • пользователь получает не огромный бандл, собранный вебпаком из скриптов и компонентов из веб-приложения, а кусок HTML и небольшой кусок-довесок из кода.

Всё это прекрасно работало. Кроме последнего пункта. 

Overсборка

Мы когда-то заморочились со сборками и всё прекрасно отладили. Сборка была компактной, правильно «побитой», лишнего особо ничего не улетало. 

А когда взяли webpack-bundle-analyzer, проанализировали текущую нашу сборку и удивились. В сборке оказалось много неиспользуемого. 

Мы решили начать с нуля, применив практики по оптимизации и ускорению:

1. Грамотно поделили сервисы на чанки;

2. Настроили хороший tree-shaking с помощью Webpack 5;

3. Использовали Preact в режиме compat;

4. Применили content-visibility для изображений;

5. Заинлайнили критический CSS;

6. Убрали неиспользуемые зависимости.

Подробности расскажем ниже.

Артефакты прошлых лет

На заре разработки микросервисов мы использовали глобальные CSS-файлы и Sentry для мониторинга. Со временем мы от этого отошли, но сами файлы так и продолжили подключаться на всех страницах, хоть и использовались лишь в паре старых сервисов:

  1. common.css — базовые стили, reset.css и пр.;

  2. grid.css — старая сетка сайта;

  3. sentry.js — инструмент для сбора всех клиентских ошибок. Со временем нам стало очевидно, что мы не хотим собирать всё подряд, и на смену этой библиотеке пришла наша, более легковесная и простая, но мы не убрали эту.

Что мы сделали:

  1. grid.css унесли в единственные её использующие 2 старых сервиса;

  2. common.css перенесли с CDN прямо в код HTML;

  3. sentry.js просто удалили.

Inline CSS

Чуть-чуть остановимся на прямом включении CSS. Это хорошее решение для улучшения CLS. Если происходит что-то на линии и внезапно лаги нападают именно на CSS-файл (особенно когда все стили проекта и сторонних библиотек добросовестно собраны вебпаком в один красивый большой файл), а скрипты и сама страница подгрузились, то браузер пытается всё отрисовать. Потом стили долетают, и всё начинает судорожно перестраиваться.

Поэтому выносить компактный набор стилей, управляющий в первую очередь макетом и основной цветошрифтовой палитрой, оказалось хорошей идеей.

Время менять шапки

В Циан мы используем микросервисную архитектуру. Обычно в формировании страницы со стороны фронтенда участвует 3 сервиса: шапка, футер и микросервис конкретной страницы. Это сильно упрощает разработку и ускоряет деплой.

Самым медленным микросервисом оказалась шапка. Проблема была на стороне браузера: много стилей, много JS, крайне неоптимальное чанкование, проблемы с зависимостями и т. д. 

Мы поняли очевидное: шапка будет развиваться в плане функционала. Какие бы мы оптимизации ни включили в текущей архитектуре, так мы только отложим проблемы. Поэтому мы решили переписать шапку полностью. 

Причины тотального рефакторинга таковы:

  • архитектура устарела, новые функции требовали слишком много бойлерплейта для реализации;

  • текущая архитектура не предполагала ленивой загрузки функции;

  • компонентный набор устарел;

  • не было возможности кластеризации в части SSR.

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

Основной идеей стала загрузка по требованию. Шапка реализована не микроприложением, а куском HTML с теми функциями, которые нужны здесь и сейчас. Более того, большинство действий, которые можно выполнить с шапки, дозагружаются сразу после клика. Например, можно авторизоваться, кликнув по «Войти». В норме это незаметно, но мы предусмотрели и обработку ситуаций, когда нам не удаётся оперативно дозагрузить (обычно предупреждалка и/или повторная попытка подгрузки).

Теперь шапку необходимо было оттестировать и замерить. После внутренних тестов мы выложили новую шапку в A/B-режиме. Мы внимательно смотрели за логами и ловили обращения в службу поддержки. 

У нас изменилась структура деплоя, потому что микросервис шапки стал масштабируемым, и проблемы производительности SSR стало возможно решать «грубой силой», просто добавляя мощности.

И вскоре на новую шапку переехала и адаптивная (десктопная) версия. 

Content-visibility

Наша выдача состоит из 28 объявлений, и обычно в каждом объявлении есть как минимум 3 фотографии. Мы использовали стандартную ленивую загрузку изображений при пролистывании галереи, но не учли, что при загрузке страницы нам не нужны изображения объявлений, которые находятся за начальной областью видимости.

Мы начали использовать CSS-свойство content-visibility. Браузеры умные: они начинают загружать изображения заранее, при «приближении» к ним, а не только когда уже виден серый прямоугольник. Мы использовали это свойство только и именно для картинок, что снизило время браузера на рендеринг страницы чуть ли не вполовину. Обычно пользователи приходят на выдачу с заранее накрученными параметрами: цена, комиссии и прочее их уже устраивают. И смотрят они именно на картинки.

Попутные находки

Мы используем React в разработке, а для прода — Preact в режиме Compact. Поскольку Preact на 99 % совместим, то всё взлетело с первого раза и дало как увеличение скорости рендера, так и уменьшение бандлов.

Иконки были сделаны универсально, как SVG. Неважно, являлись ли они растром PNG или вектором. Добрый webpack, видя PNG’шку в SVG’шке, преобразует файл картинки в Base64 и подключает его в бандл. Пришлось это почистить. 

Подводим итоги

Что у нас получилось со страницей поисковой выдачи на мобилке:

Было

Стало

Размер JS-бандла

500 kB gzipped

100 kB gzipped

FCP

4.3 s

2.8 s 

LCP

5.0 s

3.8 s

CLS

0.002

0.002

TTI

9.1 s

5.7 s

TBT

570 ms

490 ms

А вот наши итоги в целом:

  • Нам удалось войти в зелёные зоны по всем метрикам. 

  • Мы получили улучшенный, расширяемый и масштабируемый код.

  • Мы осознали, насколько важно взаимодействовать не только с пользователями, но и с другими подразделениями Циан, и разработали каналы коммуникации и обратной связи.

  • Мы поняли необходимость и методы ранней диагностики проблем, в том числе с использованием метрик CWV.

  • Мы сделали наших пользователей чуть-чуть счастливее.

Источник: https://habr.com/ru/company/cian/blog/598799/


Интересные статьи

Интересные статьи

Парламент Португалии утвердил новые поправки, защищающие удаленных сотрудников. Власти страны решили адаптировать трудовое законодательство, учитывая увеличение числа людей, работающих дома во вре...
Недавно на проекте интегрировал модуль CRM Битрикса c виртуальной АТС Ростелеком. Делал по стандартной инструкции, где пошагово показано, какие поля заполнять. Оказалось, следование ей не гаран...
Принимая решения о переезде в ту или иную страну или город, приходится делать выбор. Чаще всего это конечно выбор “ехать” или “не ехать”, но более удачливым приходится выбирать и из...
Как широко известно, с 1 января 2017 года наступает три важных события в жизни интернет-магазинов.
К настоящему моменту я владею несколькими тематическими порталами, которые успешно загибаются. И в этой статье я расскажу о том, как я их сделал, сколько получил, и почему им приходит конец, ...