Повышение производительности веб-сайтов стало проще — выпуск Google I/O 2018

На конференции Google IO 2018 мы представили обзор инструментов, библиотек и методов оптимизации, которые упрощают повышение производительности веб-сайтов. Здесь мы расскажем о них на примере приложения The Oodles Theater. Мы также поделимся впечатлениями от наших экспериментов с предиктивной загрузкой и новой инициативой Guess.js.

Ewa Gasperowicz

В течение последнего года мы были довольно заняты поиском способов ускорения и повышения производительности веб-сайтов. Это привело к созданию новых инструментов, подходов и библиотек, которыми мы хотели бы поделиться с вами в этой статье. В первой части мы покажем вам некоторые методы оптимизации, которые мы использовали на практике при разработке приложения The Oodles Theater . Во второй части мы расскажем о наших экспериментах с предиктивной загрузкой и новой инициативой Guess.js .

Необходимость в результативности

Интернет с каждым годом становится всё тяжелее. Если мы посмотрим на состояние сети, то увидим, что средняя страница на мобильном устройстве весит около 1,5 МБ, причём большая часть этого веса приходится на JavaScript и изображения.

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

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

Иерархия UX пирамида
Рис. 1. Насколько важна скорость для пользователей? (Speed ​​Matters, Vol. 3)

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

Lighthouse — основа для оптимизации рабочих процессов.

Lighthouse — это часть Chrome DevTools, которая позволяет провести аудит вашего веб-сайта и дать советы по его улучшению.

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

Новые аудиты маяка
Рис. 2. Новые проверки маяка.

Давайте рассмотрим, как вы можете воспользоваться ими на практическом примере: приложение Oodles Theater . Это небольшое демонстрационное веб-приложение, где вы можете попробовать некоторые из наших любимых интерактивных дудлов Google и даже сыграть в одну-две игры.

При разработке приложения мы хотели убедиться в его максимальной производительности. Отправной точкой для оптимизации стал отчет Lighthouse.

Отчет о маяке для приложения Oodles
Рис. 3. Отчет о маяке для приложения Oodles.

Первоначальная производительность нашего приложения, согласно отчету Lighthouse, была довольно ужасной. В сети 3G пользователю приходилось ждать 15 секунд до первой значимой отрисовки или до того, как приложение станет интерактивным. Lighthouse выявил множество проблем с нашим сайтом, и общий показатель производительности, равный 23, точно это подтвердил.

Страница весила около 3,4 МБ — нам срочно нужно было избавиться от лишнего.

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

Возможности оптимизации производительности

Удалите ненужные ресурсы

Есть несколько очевидных вещей, которые можно безопасно удалить: пробелы и комментарии.

Преимущества минимизации
Рис. 4. Минимизация и сжатие JavaScript и CSS.

Компания Lighthouse подчеркивает эту возможность в своем аудите Unminified CSS & JavaScript . Мы использовали webpack для процесса сборки, поэтому для минификации мы просто воспользовались плагином Uglify JS .

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

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

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

Хотя gzip — очень популярный способ сжатия, другие механизмы, такие как Zopfli и Brotli, также набирают популярность. Brotli поддерживается большинством браузеров, и вы можете использовать бинарный файл для предварительного сжатия ваших ресурсов перед отправкой их на сервер.

Используйте эффективные политики кэширования.

Следующим шагом было убедиться, что мы не отправляем ресурсы дважды, если это не требуется.

Аудит неэффективной политики кэширования в Lighthouse помог нам заметить, что мы могли бы оптимизировать наши стратегии кэширования именно для достижения этой цели. Установив заголовок истечения срока действия max-age на нашем сервере, мы гарантировали, что при повторном посещении пользователь сможет повторно использовать ресурсы, которые он загрузил ранее.

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

Удалите неиспользуемый код

До сих пор мы удаляли очевидные, ненужные части загрузки, но что делать с менее очевидными частями? Например, с неиспользуемым кодом.

Анализ покрытия кода в инструментах разработчика
Рис. 5. Проверка покрытия кода.

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

Вначале мы использовали библиотеку Material Components для быстрого создания прототипов нашего приложения. Со временем мы перешли к более индивидуальному дизайну и полностью забыли об этой библиотеке. К счастью, проверка покрытия кода помогла нам заново обнаружить её в нашем бандле.

В инструментах разработчика можно проверить статистику покрытия кода как во время выполнения, так и во время загрузки приложения. На нижнем скриншоте видны две большие красные полосы — у нас более 95% CSS-кода оставалось неиспользованным, а также большое количество JavaScript-кода.

Lighthouse также обнаружил эту проблему в ходе аудита неиспользуемых правил CSS. Он показал потенциальную экономию более 400 КБ. Поэтому мы вернулись к нашему коду и удалили как JavaScript, так и CSS-часть этой библиотеки.

Если мы откажемся от MVC-адаптера, размер наших стилей сократится до 10 КБ.
Рис. 6. Если мы уберем MVC-адаптер, размер наших стилей уменьшится до 10 КБ!

Это позволило уменьшить размер нашего CSS-пакета в 20 раз, что довольно неплохо для такого небольшого, всего лишь двухстрочного коммита.

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

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

Наш код не использовался на 95%, а оставшиеся 5% всё ещё где-то лежат. Оказывается, один из наших компонентов всё ещё использовал стили из этой библиотеки — маленькие стрелки в слайдере с рисунками. Но поскольку это было совсем небольшое изменение, мы смогли просто вручную добавить эти стили обратно в кнопки.

Кнопки сломались из-за отсутствия библиотеки.
Рис. 7. Один из компонентов по-прежнему использовал удаленную библиотеку.

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

Избегайте чрезмерно больших сетевых нагрузок.

Мы знаем, что большие объемы ресурсов могут замедлять загрузку веб-страниц. Это может стоить нашим пользователям денег и существенно повлиять на их тарифные планы, поэтому очень важно это учитывать.

С помощью инструмента аудита сетевых нагрузок Enormous Lighthouse удалось обнаружить проблему с некоторыми из наших сетевых пакетов.

Обнаружение огромных сетевых нагрузок
Рис. 8. Обнаружение огромных сетевых нагрузок.

Здесь мы увидели, что в систему загружалось более 3 МБ кода — это довольно много, особенно для мобильных устройств.

В самом начале этого списка Lighthouse указал на то, что у нас был JavaScript-пакет, содержащий 2 МБ несжатого кода. Эта проблема также была выявлена ​​webpack.

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

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

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

Аудит пакетов JavaScript
Рис. 9. Аудит пакетов JavaScript.

Мы начали с анализатора пакетов webpack, который сообщил нам, что мы включили зависимость под названием unicode, которая представляла собой 1,6 МБ разобранного JavaScript-кода, то есть довольно много.

Затем мы перешли в наш редактор и, используя плагин Import Cost Plugin for Visual Code, смогли визуализировать стоимость каждого импортируемого модуля. Это позволило нам определить, какой компонент включает код, ссылающийся на этот модуль.

Затем мы переключились на другой инструмент, BundlePhobia . Это инструмент, который позволяет ввести имя любого NPM-пакета и увидеть примерный размер в сжатом и минифицированном виде. Мы нашли хорошую альтернативу используемому нами модулю slug, которая весила всего 2,2 КБ, поэтому мы перешли на него.

Это оказало значительное влияние на производительность. Благодаря этому изменению и обнаружению других возможностей для уменьшения размера нашего JavaScript-пакета, мы сэкономили 2,1 МБ кода.

В целом мы увидели улучшение на 65%, если учесть размер этих пакетов в сжатом и уменьшенном виде. И мы пришли к выводу, что этот процесс действительно стоил того.

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

Сокращение времени запуска JavaScript за счет разделения кода.

Хотя большие объемы сетевых данных могут оказать существенное влияние на наше приложение, есть еще один фактор, который может оказать действительно большое влияние, — это JavaScript.

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

Вот как браузер обрабатывает JavaScript.

Обработка JavaScript
Рис. 10. Обработка JavaScript

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

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

Чтобы помочь вам выявить эти проблемы в вашем приложении, мы добавили в Lighthouse новый аудит времени запуска JavaScript .

Время загрузки JavaScript
Рис. 11. Аудит времени запуска JavaScript.

А в случае с приложением Oodle нам показали, что на запуск JavaScript ушло 1,8 секунды. Дело в том, что мы статически импортировали все наши маршруты и компоненты в один монолитный JavaScript-пакет.

Один из способов обойти эту проблему — использовать разделение кода.

Разделение кода — это как пицца.

Разделение кода — это идея о том, что вместо того, чтобы давать пользователям целую пиццу JavaScript-кода, что если бы вы давали им только один кусочек за раз, по мере необходимости?

Разделение кода можно применять на уровне маршрута или на уровне компонента. Оно отлично работает с React и React Loadable, Vue.js, Angular, Polymer, Preact и многими другими библиотеками.

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

Разделение кода с помощью динамического импорта
Рис. 13. Разделение кода с помощью динамического импорта.

В результате этого уменьшился не только размер наших пакетов, но и сократилось время запуска JavaScript. Оно снизилось до 0,78 секунды, что сделало приложение на 56% быстрее.

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

Воспользуйтесь преимуществами таких концепций, как разделение кода, изучите идеи, такие как оптимизация кода (tree shaking), и ознакомьтесь с репозиторием webpack-libs-optimizations, чтобы получить несколько идей о том, как уменьшить размер вашей библиотеки, если вы используете webpack.

Оптимизировать изображения

шутка про производительность загрузки изображения

В приложении Oodle мы используем много изображений. К сожалению, компания Lighthouse отнеслась к этому гораздо менее восторженно, чем мы. Фактически, мы провалили все три проверки, связанные с изображениями.

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

Аудит изображений
Рис. 14. Аудит изображений маяка.

Мы начали с оптимизации изображений.

Для разовой оптимизации можно использовать визуальные инструменты, такие как ImageOptim или XNConvert .

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

Таким образом, вы гарантируете автоматическую оптимизацию изображений, добавляемых в будущем. Некоторые CDN, например Akamai , или сторонние решения, такие как Cloudinary , Fastly или Uploadcare, предлагают комплексные решения для оптимизации изображений, поэтому вы также можете просто разместить свои изображения на этих сервисах.

Если вы не хотите этого делать из-за стоимости или проблем с задержкой, такие проекты, как Thumbor или Imageflow, предлагают альтернативные варианты с самостоятельным размещением.

До и после оптимизации
Рис. 15. До и после оптимизации.

Наш фоновый PNG-файл был помечен webpack как большой, и это было справедливо. После того, как мы правильно подогнали его размер под область просмотра и обработали с помощью ImageOptim, мы уменьшили его до 100 КБ, что является приемлемым размером.

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

Используйте правильный формат для анимированного контента.

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

В приложении Oodle мы использовали GIF-анимацию в качестве вступительной заставки на главной странице. По данным Lighthouse, мы могли бы сэкономить более 7 МБ, перейдя на более эффективный видеоформат. Наш клип весил около 7,3 МБ, что слишком много для любого разумного веб-сайта, поэтому вместо этого мы превратили его в видеоэлемент с двумя исходными файлами — mp4 и WebM для более широкой поддержки браузеров.

Замените анимированные GIF-файлы видео.
Рис. 16. Замена анимированных GIF-файлов видео.

Мы использовали инструмент FFmpeg для преобразования нашей анимационной GIF-картинки в файл mp4. Формат WebM обеспечивает еще большую экономию — API ImageOptim может выполнить такое преобразование за вас.

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

Благодаря этой модернизации нам удалось сэкономить более 80% от общего веса. В результате объем нашей продукции снизился примерно до 1 МБ.

Тем не менее, 1 МБ — это большой объем данных для передачи по сети, особенно для пользователя с ограниченной пропускной способностью. К счастью, мы смогли использовать API эффективных типов, чтобы определить, что у них низкая пропускная способность, и предоставить им гораздо меньший по размеру JPEG-файл.

Этот интерфейс использует эффективное время кругового пути и значения скорости загрузки для оценки типа сети, которую использует пользователь. Он просто возвращает строку: медленная 2G, 2G, 3G или 4G. Таким образом, в зависимости от этого значения, если пользователь использует сеть ниже 4G, мы можем заменить видеоэлемент изображением.

if (navigator.connection.effectiveType) { ... }

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

Отложенная загрузка изображений, находящихся за пределами экрана.

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

Lighthouse отметит такое поведение в аудите изображений, находящихся за пределами экрана, и вы также можете увидеть это сами на панели «Сеть» в инструментах разработчика. Если вы видите много входящих изображений, в то время как на странице отображается лишь несколько, это означает, что, возможно, стоит рассмотреть вариант их отложенной загрузки.

Ленивая загрузка пока не поддерживается браузером нативно, поэтому нам приходится использовать JavaScript для добавления этой возможности. Мы использовали библиотеку Lazysizes для добавления поведения ленивой загрузки к нашим обложкам Oodle.

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

Lazysizes — это интеллектуальная функция, которая не только отслеживает изменения видимости элемента, но и заблаговременно загружает элементы, находящиеся рядом с видимой областью, для оптимального пользовательского опыта. Она также предлагает дополнительную интеграцию с IntersectionObserver , что обеспечивает очень эффективный поиск информации о видимости.

После этого изменения изображения будут загружаться по запросу. Если вы хотите подробнее изучить эту тему, ознакомьтесь с images.guide — очень удобным и всеобъемлющим ресурсом.

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

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

Полезным было бы, если бы мы, как авторы страницы, сообщали браузеру, что для нас действительно важно. К счастью, за последние пару лет производители браузеров добавили ряд функций, помогающих нам в этом, например, подсказки о ресурсах, такие как link rel=preconnect , preload или prefetch .

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

Давайте посмотрим, как Lighthouse на самом деле помогает нам эффективно использовать некоторые из этих функций.

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

Избегайте многочисленных и дорогостоящих поездок туда и обратно в любой пункт отправления.
Рис. 17. Избегайте многократных и дорогостоящих поездок туда и обратно к месту отправления.

В случае с приложением Oodle мы активно используем шрифты Google Fonts. Каждый раз, когда вы добавляете таблицу стилей Google Fonts на свою страницу, она подключается к двум поддоменам. И, как показывает Lighthouse, если бы мы смогли ускорить это соединение, мы могли бы сэкономить до 300 миллисекунд на времени первоначального подключения.

Используя функцию предварительного подключения link rel preconnect, мы можем эффективно замаскировать задержку соединения.

Особенно в случае с Google Fonts, где наши CSS-файлы шрифтов размещены на googleapis.com , а ресурсы шрифтов — на Gstatic , это может оказать действительно большое влияние. Поэтому мы применили эту оптимизацию и сэкономили несколько сотен миллисекунд.

Следующее, что предлагает Lighthouse, — это предварительная загрузка ключевых запросов.

Запросы на предварительную загрузку ключей
Рис. 18. Запросы на предварительную загрузку ключей.

<link rel=preload> — действительно мощный инструмент, он сообщает браузеру о необходимости ресурса в рамках текущей навигации и пытается как можно быстрее обеспечить его загрузку.

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

Предварительная загрузка веб-шрифта выглядит следующим образом: указав rel=preload , вы as тип шрифта, а затем указываете тип шрифта, который пытаетесь загрузить, например, woff2.

Влияние этого на вашу страницу может быть весьма существенным.

Влияние предварительной загрузки ресурсов
Рис. 19. Влияние ресурсов предварительной загрузки.

Обычно, без использования link rel preload, если веб-шрифты критически важны для вашей страницы, браузеру сначала нужно загрузить ваш HTML-код, затем проанализировать ваш CSS-код, и, наконец, гораздо позже, он загрузит ваши веб-шрифты.

Использование атрибута `link rel preload` позволяет браузеру начать загрузку веб-шрифтов сразу после обработки HTML-кода. В случае нашего приложения это позволило сократить время отображения текста с использованием веб-шрифтов на секунду.

Однако, если вы собираетесь предварительно загрузить шрифты с помощью Google Fonts, все не так просто, есть один нюанс.

Ссылки на шрифты Google Fonts, которые мы указываем в наших таблицах стилей, довольно регулярно обновляются командой разработчиков шрифтов. Эти ссылки могут устаревать или обновляться с задержкой, поэтому, если вы хотите полностью контролировать загрузку шрифтов, мы бы рекомендовали разместить ваши веб-шрифты на собственном сервере. Это может быть очень удобно, поскольку дает доступ к таким функциям, как предварительная загрузка ссылок (link rel preload).

В нашем случае нам очень помог инструмент Google Web Fonts Helper, который позволил нам установить некоторые из этих веб-шрифтов в автономном режиме и настроить их локально, так что обязательно попробуйте этот инструмент.

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

Экспериментальный режим: Подсказки по приоритетам

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

Установите приоритет для изначально видимого контента.
Рис. 20. Подсказки о приоритетах

Это новая функция, позволяющая сообщать браузеру о важности ресурса. Она предоставляет новый атрибут — importance — со значениями low, high или auto.

Это позволяет нам снижать приоритет менее важных ресурсов, таких как некритичные стили, изображения или вызовы API для получения данных, чтобы уменьшить конкуренцию. Мы также можем повышать приоритет более важных элементов, таких как изображения в заголовке страницы.

В случае с нашим приложением на Oodle это фактически привело к одному практическому результату, который мы смогли оптимизировать.

Установите приоритет для изначально видимого контента.
Рис. 21. Установите приоритет для изначально видимого контента.

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

Мы надеемся добавить эту функцию в Canary через несколько недель, так что следите за обновлениями.

Разработайте стратегию загрузки веб-шрифтов.

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

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

Избегайте появления невидимого текста во время загрузки веб-шрифтов.
Рис. 22. Избегайте невидимого текста во время загрузки веб-шрифтов.

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

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

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

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

В данном случае мы используем функцию смены шрифта. Функция смены шрифта задаёт нулевой блочный период для основного шрифта и бесконечный период смены. Это означает, что браузер будет отображать ваш текст практически мгновенно, используя резервный шрифт, если загрузка основного шрифта займёт некоторое время. И он заменит его, как только основной шрифт станет доступен.

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

Результат отображения шрифта
Рис. 23. Результат отображения шрифта.

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

Существует множество функций веб-платформы, которые можно использовать для оптимизации загрузки шрифтов, но также обратите внимание на репозиторий Web Font Recipes Зака ​​Лезермана, потому что он действительно замечательный.

Уменьшите количество скриптов, блокирующих отрисовку.

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

На временной шкале Lighthouse видно, что в первые несколько секунд, когда загружаются все ресурсы, пользователь фактически не видит никакого контента.

Уменьшить вероятность блокировки отрисовки таблиц стилей.
Рис. 24. Возможность уменьшить блокировку рендеринга в таблицах стилей.

Загрузка и обработка внешних таблиц стилей блокирует дальнейший процесс рендеринга.

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

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

В нашем случае мы использовали модуль NPM под названием Critical для встраивания критически важного контента в файл index.html на этапе сборки.

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

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

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

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

Результат

Это был длинный список оптимизаций производительности, которые мы применили к нашему сайту. Давайте посмотрим на результат. Вот как наше приложение загружалось на мобильном устройстве среднего размера в сети 3G до и после оптимизации.

Показатель производительности Lighthouse вырос с 23 до 91. Это довольно хороший прогресс с точки зрения скорости. Все изменения стали возможны благодаря постоянной проверке и отслеживанию отчета Lighthouse. Если вы хотите узнать, как мы технически реализовали все эти улучшения, загляните в наш репозиторий , особенно в раздел запросов на слияние (PR), которые там появились.

Прогнозируемая производительность — пользовательский опыт на основе данных

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

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

Сегодня у нас есть данные, которые позволяют нам эффективнее проводить оптимизацию. Используя API отчетов Google Analytics, мы можем проанализировать следующие страницы в списке самых популярных и процент отказов для любого URL-адреса на нашем сайте, и, следовательно, сделать выводы о том, каким ресурсам следует уделить приоритетное внимание.

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

Сборка веб-приложений на основе данных
Рис. 25. Объединение веб-приложений на основе данных.

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

Guess.js
Рис. 26. Guess.js

Guess.js — это проект, ориентированный на создание пользовательского опыта в веб-среде на основе данных. Мы надеемся, что он вдохновит на изучение способов использования данных для улучшения производительности веб-сайтов и выйдет за их рамки. Проект полностью с открытым исходным кодом и доступен на GitHub уже сегодня. Он был создан в сотрудничестве с сообществом разработчиков открытого исходного кода Минко Гечевым, Кайлом Мэтьюзом из Gatsby, Кэти Хемпениус и рядом других.

Ознакомьтесь с Guess.js и поделитесь своим мнением.

Краткое содержание

Показатели и метрики помогают повысить скорость работы Интернета, но они являются лишь средством, а не самоцелью.

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

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

Выражаем особую благодарность: Уорду Питерсу, Минко Гечеву, Кайлу Мэтьюсу, Кэти Хемпениус, Дому Фаролино, Йоаву Вайссу, Сьюзи Лу, Юсуке Уцуномии, Тому Анкерсу, Lighthouse и Google Doodle.