Веб-производительность стала проще – Google I/O, выпуск 2018 г.

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

Адди Османи
Addy Osmani
Ewa Gasperowicz

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

Потребность в производительности

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

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

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

Пирамида UX-иерархии
Рис. 1. Насколько важна скорость для пользователей? (Скорость имеет значение, Том 3)

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

Lighthouse — основа для рабочего процесса производительности

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

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

Аудит нового маяка
Рис. 2. Аудиты New Lighthouse

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

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

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

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

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

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

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

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

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

Выгоды от минификации
Рис. 4. Минимизация и сжатие JavaScript и CSS

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

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

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

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

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

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

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

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

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

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

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

Покрытие кода в DevTools
Рис. 5. Проверка покрытия кода

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

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

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

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

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

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

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

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

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

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

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

Избегайте огромной полезной нагрузки в сети

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

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

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

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

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

Как говорится: самый быстрый запрос — тот, который не выполнен.

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

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

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

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

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

Затем мы переключились на другой инструмент — 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, обязательно отправляйте пользователю только тот код, который ему нужен.

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

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

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

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

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

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

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

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

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

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

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

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

Наш фоновый PNG был помечен в веб-пакете как большой, и это правильно. После правильного определения размера в области просмотра и запуска через 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 будет отмечать это поведение при аудите закадровых изображений, и вы также можете увидеть это самостоятельно на сетевой панели DevTools. Если вы видите много входящих изображений, а на странице видны лишь некоторые, это означает, что, возможно, вместо этого вы могли бы рассмотреть возможность их ленивой загрузки.

Отложенная загрузка еще не поддерживается браузером изначально, поэтому нам придется использовать 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 на самом деле помогает нам эффективно использовать некоторые из этих функций.

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

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

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

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

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

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

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

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

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

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

Влияние, которое это может оказать на вашу страницу, весьма резкое.

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

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

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

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

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

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

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

Эксперимент: подсказки по приоритету

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

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

Это новая функция, которая позволяет намекнуть браузеру, насколько важен тот или иной ресурс. Он предоставляет новый атрибут — важность — со значениями 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');
    }

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

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

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

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

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

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

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

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

На временной шкале 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 сегодня. Он был создан в сотрудничестве с сообществом открытого исходного кода Минко Гечевым, Кайлом Мэтьюзом из «Гэтсби», Кэти Хемпениус и рядом других.

Ознакомьтесь с Guess.js и сообщите нам, что вы думаете.

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

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

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

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

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