Как мы улучшили наши основные веб-жизненные показатели (пример из практики)

Опубликовано: 2022-03-10
Краткий обзор ↬ «Обновление качества страницы» от Google начнет развертываться в июне. Поначалу сайты, соответствующие пороговым значениям Core Web Vitals, будут иметь незначительное преимущество в рейтинге в мобильном поиске для всех браузеров. Поиск важен для любого бизнеса, и это история о том, как Бо Хартсхорн и его команда из Instant Domain Search улучшили свои показатели Core Web Vitals. Кроме того, они создали инструмент с открытым исходным кодом.

В прошлом году Google начал подчеркивать важность Core Web Vitals и того, как они отражают реальный опыт человека при посещении сайтов в Интернете. Производительность — это ключевая особенность нашей компании, Мгновенный поиск доменов — это указано в названии. Каково же было наше удивление, когда мы обнаружили, что наши жизненные показатели не очень хороши для многих людей. Наши быстрые компьютеры и оптоволоконный интернет маскировали опыт реальных людей на нашем сайте. Это было незадолго до того, как море красных «плохих» и желтых «требует улучшения» уведомлений в нашей консоли поиска Google потребовало нашего внимания. Энтропия победила, и нам нужно было придумать, как избавиться от мусора и сделать наш сайт быстрее.

Скриншот из Google Search Console, показывающий, что нам нужно улучшить показатели Core Web Vitals.
Это скриншот из нашего мобильного отчета Core Web Vitals в Google Search Console. У нас еще много работы! (Большой превью)

Я основал Instant Domain Search в 2005 году и использовал его как подработку, пока работал в компании Y Combinator (Snipshot, W06), прежде чем работать инженером-программистом в Facebook. Недавно мы превратились в небольшую группу, базирующуюся в основном в Виктории, Канада, и работаем над большим количеством новых функций и улучшений производительности. Наши низкие показатели веб-показателей и надвигающееся обновление Google заставили нас сосредоточиться на поиске и устранении этих проблем.

Когда была запущена первая версия сайта, я создал ее с помощью PHP, MySQL и XMLHttpRequest. Internet Explorer 6 полностью поддерживался, доля Firefox набирала обороты, а до запуска Chrome оставалось еще несколько лет. Со временем мы эволюционировали с помощью множества генераторов статических сайтов, фреймворков JavaScript и серверных технологий. Наш текущий внешний стек — это React, обслуживаемый Next.js, и встроенный в Rust серверный сервис для ответа на наши поиски по доменным именам. Мы стараемся следовать передовой практике, обслуживая как можно больше через CDN, избегая как можно большего количества сторонних скриптов и используя простую графику SVG вместо растровых изображений PNG. Этого было недостаточно.

Next.js позволяет нам создавать наши страницы и компоненты в React и TypeScript. В сочетании с VS Code опыт разработки потрясающий. Next.js обычно работает путем преобразования компонентов React в статический HTML и CSS. Таким образом, начальный контент может быть доставлен из CDN, а затем Next может «гидратировать» страницу, чтобы сделать элементы динамичными. После заполнения страницы наш сайт превращается в одностраничное приложение, в котором люди могут искать и генерировать доменные имена. Мы не полагаемся на Next.js для выполнения большой части работы на стороне сервера, большая часть нашего контента статически экспортируется в виде HTML, CSS и JavaScript для обслуживания из CDN.

Еще после прыжка! Продолжить чтение ниже ↓

Когда кто-то начинает искать доменное имя, мы заменяем содержимое страницы результатами поиска. Чтобы сделать поиск как можно быстрее, интерфейс напрямую запрашивает наш сервер Rust, который сильно оптимизирован для поиска доменов и предложений. На многие запросы мы можем ответить мгновенно, но для некоторых TLD нам нужно выполнять более медленные DNS-запросы, на решение которых может уйти секунда или две. Когда некоторые из этих более медленных запросов будут разрешены, мы обновим пользовательский интерфейс с учетом новой поступающей информации. Страницы результатов у всех разные, и нам может быть трудно точно предсказать, как каждый человек воспринимает сайт.

Инструменты Chrome DevTools превосходны и являются хорошей отправной точкой при поиске проблем с производительностью. Представление «Производительность» точно показывает, когда отправляются HTTP-запросы, где браузер тратит время на оценку JavaScript и многое другое:

Скриншот панели «Производительность» в Chrome DevTools
Скриншот панели «Производительность» в Chrome DevTools. Мы включили Web Vitals, что позволяет нам увидеть, какой элемент вызвал LCP. (Большой превью)

Есть три показателя Core Web Vitals, которые Google будет использовать для ранжирования сайтов в предстоящем обновлении поискового алгоритма. Google разделяет опыт на «Хороший», «Требует улучшения» и «Плохой» на основе оценок LCP, FID и CLS, которые реальные люди имеют на сайте:

  • LCP , или Largest Contentful Paint, определяет время, необходимое для того, чтобы самый большой элемент контента стал видимым.
  • FID , или задержка первого ввода, связана с реакцией сайта на взаимодействие — временем между касанием, щелчком или нажатием клавиши в интерфейсе и ответом со страницы.
  • CLS , или Cumulative Layout Shift, отслеживает, как элементы перемещаются или сдвигаются на странице без каких-либо действий, таких как нажатие клавиатуры или событие щелчка.
Графика, показывающая диапазоны допустимых показателей LCP, FID и CLS
Сводка LCP, FID и CLS. (Изображение предоставлено: Web Vitals Филипа Уолтона) (Большой предварительный просмотр)

Chrome настроен на отслеживание этих показателей для всех вошедших в систему пользователей Chrome и отправляет анонимную статистику, обобщающую опыт пользователя на сайте, обратно в Google для оценки. Эти оценки доступны через отчет о пользовательском опыте Chrome и отображаются при проверке URL-адреса с помощью инструмента PageSpeed ​​Insights. Баллы представляют собой 75-й процентиль опыта для людей, посетивших этот URL-адрес за предыдущие 28 дней. Это число, которое они будут использовать для ранжирования сайтов в обновлении.

Метрика 75-го процентиля (p75) обеспечивает разумный баланс для целей производительности. Взятие среднего значения, например, скроет много негативного опыта людей. Медиана, или 50-й процентиль (p50), будет означать, что половина людей, использующих наш продукт, испытывают худшие впечатления. С другой стороны, 95-й процентиль (p95) сложно построить, поскольку он фиксирует слишком много экстремальных выбросов на старых устройствах с нестабильным подключением. Мы считаем, что оценка на основе 75-го процентиля является справедливым стандартом.

Диаграмма, иллюстрирующая распределение значений p50 и p75
Медиана, также известная как 50-й процентиль или p50, показана зеленым цветом. 75-й процентиль, или p75, показан здесь желтым цветом. На этой иллюстрации мы показываем 20 сеансов. 15-й худший сеанс — это 75-й процентиль, который Google будет использовать для оценки опыта этого сайта. (Большой превью)

Чтобы контролировать свои оценки, мы сначала обратились к Lighthouse за отличными инструментами, встроенными в Chrome и размещенными на веб-сайтах web.dev/measure/ и PageSpeed ​​Insights. Эти инструменты помогли нам найти некоторые общие технические проблемы с нашим сайтом. Мы увидели, что то, как Next.js объединяет наш CSS, замедляет время первоначального рендеринга, что влияет на наш FID. Первая легкая победа пришлась на экспериментальную функцию Next.js, optim Css, которая помогла значительно улучшить нашу общую оценку производительности.

Lighthouse также обнаружила неправильную конфигурацию кеша, из-за которой некоторые из наших статических ресурсов не обслуживались из нашей CDN. Мы размещены на Google Cloud Platform, и Google Cloud CDN требует, чтобы заголовок Cache-Control содержал «public». Next.js не позволяет настраивать все генерируемые им заголовки, поэтому нам пришлось переопределить их, поместив сервер Next.js за Caddy, облегченным прокси-сервером HTTP, реализованным в Go. Мы также воспользовались возможностью, чтобы убедиться, что мы обслуживаем все, что можем, с относительно новой поддержкой stale-while-revalidate в современных браузерах, которая позволяет CDN получать контент из источника (нашего сервера Next.js) асинхронно в фоновом режиме.

Легко — может быть, даже слишком просто — добавить практически все, что вам нужно, в ваш продукт из npm. Рост размеров пакетов не займет много времени. Большие пакеты загружаются дольше в медленных сетях, и мобильный телефон 75-го процентиля будет тратить много времени, блокируя основной поток пользовательского интерфейса, пытаясь понять весь код, который он только что скачал. Нам понравился BundlePhobia — бесплатный инструмент, который показывает, сколько зависимостей и байтов пакет npm добавит к вашему пакету. Это привело к тому, что мы исключили или заменили ряд анимаций, основанных на реакции, более простыми переходами CSS:

Скриншот инструмента BundlePhobia, показывающий, что react-spring добавляет 162,8 КБ JavaScript
Мы использовали BundlePhobia, чтобы помочь отследить большие зависимости, без которых мы могли бы жить. (Большой превью)

Благодаря использованию BundlePhobia и Lighthouse мы обнаружили, что стороннее программное обеспечение для регистрации ошибок и аналитики значительно увеличивает размер нашего пакета и время загрузки. Мы удалили эти инструменты и заменили их собственными средствами ведения журналов на стороне клиента, которые используют преимущества современных API-интерфейсов браузера, таких как sendBeacon и ping. Мы отправляем журналы и аналитику в нашу собственную инфраструктуру Google BigQuery, где мы можем ответить на интересующие нас вопросы более подробно, чем любой из готовых инструментов. Это также устраняет ряд сторонних файлов cookie и дает нам гораздо больший контроль над тем, как и когда мы отправляем данные журналов от клиентов.

Наш показатель CLS по-прежнему имел наибольшие возможности для улучшения. Способ, которым Google рассчитывает CLS, сложен: вам предоставляется максимальное «окно сеанса» с интервалом в 1 секунду, ограниченное 5 секундами с момента начальной загрузки страницы или с помощью клавиатуры или клика, чтобы завершить перемещение элементов по сайту. . Если вы заинтересованы в более глубоком изучении этой темы, вот отличное руководство по этой теме. Это наказывает многие типы оверлеев и всплывающих окон, которые появляются сразу после того, как вы попадаете на сайт. Например, реклама, которая перемещает контент или увеличивает продажи, которые могут появиться, когда вы начинаете прокручивать прошлые объявления, чтобы добраться до контента. В этой статье дается отличное объяснение того, как рассчитывается оценка CLS, и причины, лежащие в ее основе.

Мы принципиально против такого цифрового беспорядка, поэтому мы были удивлены, увидев, сколько возможностей для улучшения Google настаивает на том, чтобы мы сделали. В Chrome есть встроенный оверлей Web Vitals, к которому вы можете получить доступ, используя меню команд, чтобы «Показать оверлей Core Web Vitals». Чтобы точно увидеть, какие элементы Chrome учитывает при расчете CLS, мы обнаружили, что опция «Ведение журнала консоли» расширения Chrome Web Vitals в настройках более полезна. После включения этот плагин показывает ваши оценки LCP, FID и CLS для текущей страницы. В консоли вы можете точно увидеть, какие элементы на странице связаны с этими оценками. У наших показателей CLS было больше всего возможностей для улучшения.

Скриншот внешнего вида подключаемого модуля Chrome Web Vitals
Расширение Chrome Web Vitals показывает, как Chrome оценивает текущую страницу по показателям веб-показателей. Некоторые из этих функций будут встроены в Chrome 90. (Большой предварительный просмотр)

Из трех показателей только CLS накапливается по мере взаимодействия со страницей. Расширение Web Vitals имеет параметр ведения журнала, который точно покажет, какие элементы вызывают CLS, когда вы взаимодействуете с продуктом. Посмотрите, как увеличиваются показатели CLS, когда мы прокручиваем домашнюю страницу Smashing Magazine:

Если в расширении Chrome Web Vitals включено ведение журнала, изменения макета регистрируются в консоли, когда вы взаимодействуете с сайтом.

Google будет продолжать корректировать способ расчета CLS с течением времени, поэтому важно быть в курсе, следя за блогом веб-разработки Google. При использовании таких инструментов, как расширение Chrome Web Vitals, важно включить дросселирование ЦП и сети, чтобы получить более реалистичный опыт. Вы можете сделать это с помощью инструментов разработчика, имитируя мобильный процессор.

Снимок экрана, показывающий, как включить регулирование ЦП в Chrome DevTools.
При поиске проблем Web Vitals на вашем сайте важно имитировать более медленный процессор и сетевое соединение. (Большой превью)

Лучший способ отслеживать прогресс от одного развертывания до другого — измерять впечатления от страницы так же, как это делает Google. Если у вас настроена Google Analytics, простой способ сделать это — установить модуль Google web-vitals и подключить его к Google Analytics. Это обеспечивает приблизительную оценку вашего прогресса и делает его видимым на панели инструментов Google Analytics.

Диаграмма, показывающая средние баллы для наших значений CLS с течением времени
Google Analytics может показать среднее значение ваших показателей веб-жизненных показателей. (Большой превью)

Здесь мы наткнулись на стену. Мы могли видеть нашу оценку CLS, и хотя мы значительно улучшили ее, нам еще предстояло поработать. Наш показатель CLS был примерно 0,23, и нам нужно было снизить его до 0,1, а лучше до 0. Однако на данный момент мы не смогли найти что-то, что точно указывало бы нам, какие компоненты и на каких страницах по-прежнему влияют на показатель. Мы могли видеть, что Chrome раскрывает много деталей в своих инструментах Core Web Vitals, но агрегаторы журналов отбрасывают самую важную часть: какой именно элемент страницы вызвал проблему.

Снимок экрана консоли Chrome DevTools, показывающий, какие элементы вызывают CLS.
Это показывает, какие именно элементы способствуют вашей оценке CLS. (Большой превью)

Чтобы зафиксировать все необходимые нам детали, мы создали бессерверную функцию для сбора данных веб-показателей из браузеров. Поскольку нам не нужно выполнять запросы к данным в режиме реального времени, мы передаем их в потоковый API Google BigQuery для хранения. Эта архитектура означает, что мы можем недорого собрать столько точек данных, сколько сможем сгенерировать.

Изучив некоторые уроки при работе с Web Vitals и BigQuery, мы решили объединить эту функциональность и выпустить эти инструменты с открытым исходным кодом на vitals.dev.

Использование Instant Vitals — это быстрый способ начать отслеживать свои показатели Web Vitals в BigQuery. Вот пример схемы таблицы BigQuery, которую мы создаем:

Скриншот наших схем BigQuery для захвата FCP
Одна из наших схем BigQuery. (Большой превью)

Интеграция с Instant Vitals проста. Вы можете начать с интеграции с клиентской библиотекой для отправки данных в вашу серверную или бессерверную функцию:

 import { init } from "@instantdomain/vitals-client"; init({ endpoint: "/api/web-vitals" });

Затем на вашем сервере вы можете интегрироваться с серверной библиотекой, чтобы завершить схему:

 import fs from "fs"; import { init, streamVitals } from "@instantdomain/vitals-server"; // Google libraries require service key as path to file const GOOGLE_SERVICE_KEY = process.env.GOOGLE_SERVICE_KEY; process.env.GOOGLE_APPLICATION_CREDENTIALS = "/tmp/goog_creds"; fs.writeFileSync( process.env.GOOGLE_APPLICATION_CREDENTIALS, GOOGLE_SERVICE_KEY ); const DATASET_; init({ datasetId: DATASET_ID }).then().catch(console.error); // Request handler export default async (req, res) => { const body = JSON.parse(req.body); await streamVitals(body, body.name); res.status(200).end(); };

Просто вызовите streamVitals с текстом запроса и названием метрики, чтобы отправить метрику в BigQuery. Библиотека сама создаст набор данных и таблицы.

Собрав данные за день, мы выполнили такой запрос:

 SELECT `<project_name>.web_vitals.CLS`.Value, Node FROM `<project_name>.web_vitals.CLS` JOIN UNNEST(Entries) AS Entry JOIN UNNEST(Entry.Sources) WHERE Node != "" ORDER BY value LIMIT 10

Этот запрос дает такие результаты:

Стоимость Узел
4.6045324800736724E-4 /html/body/div[1]/main/div/div/div[2]/div/div/blockquote
7.183070668914928E-4 /html/body/div[1]/header/div/div/header/div
0.031002668277977697 /html/body/div[1]/footer
0.035830703317463526 /html/body/div[1]/main/div/div/div[2]
0.035830703317463526 /html/body/div[1]/footer
0.035830703317463526 /html/body/div[1]/main/div/div/div[2]
0.035830703317463526 /html/body/div[1]/main/div/div/div[2]
0.035830703317463526 /html/body/div[1]/footer
0.035830703317463526 /html/body/div[1]/footer
0.03988482067913317 /html/body/div[1]/footer

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

Оценка смещения макета рассчитывается как функция размера перемещаемого элемента и того, как далеко он заходит. В нашем представлении результатов поиска, если устройству требуется больше определенного времени для получения и отображения результатов поиска, представление результатов сворачивается до zero-height , открывая нижний колонтитул. Когда приходят результаты, нижний колонтитул перемещается вниз страницы. Большой элемент DOM, переместившийся так далеко, значительно увеличил нашу оценку CLS. Чтобы работать с этим должным образом, нам нужно реструктурировать способ сбора и отображения результатов поиска. Мы решили просто удалить нижний колонтитул в представлении результатов поиска в качестве быстрого хака, который предотвратит его подпрыгивание на медленных соединениях.

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

Google предоставляет отличные инструменты повышения производительности, встроенные в Chrome, и мы использовали их, чтобы найти и устранить ряд проблем с производительностью. Мы узнали, что полевые данные, предоставленные Google, давали хорошее представление о нашем прогрессе p75, но не содержали подробных сведений. Нам нужно было выяснить, какие именно элементы DOM вызывали сдвиги макета и задержки ввода. Как только мы начали собирать свои собственные полевые данные — с помощью запросов XPath — мы смогли определить конкретные возможности для улучшения работы нашего сайта для всех. Приложив некоторые усилия, мы довели наши реальные показатели Core Web Vitals до приемлемого уровня в рамках подготовки к июньскому обновлению Page Experience. Мы рады видеть, что эти цифры идут вниз и вправо!

Скриншот Google PageSpeed ​​Insights, показывающий, что мы проходим оценку Core Web Vitals
Google PageSpeed ​​Insights показывает, что теперь мы проходим оценку Core Web Vitals. (Большой превью)