Front-End Performance 2021: оптимизация активов
Опубликовано: 2022-03-10Это руководство было любезно поддержано нашими друзьями из LogRocket, службы, которая сочетает в себе мониторинг производительности внешнего интерфейса , воспроизведение сеанса и аналитику продукта, чтобы помочь вам повысить качество обслуживания клиентов. LogRocket отслеживает ключевые показатели, в т.ч. DOM завершен, время до первого байта, задержка первого ввода, использование клиентского ЦП и памяти. Получите бесплатную пробную версию LogRocket сегодня.
Оглавление
- Подготовка: планирование и показатели
- Постановка реалистичных целей
- Определение среды
- Оптимизация активов
- Оптимизация сборки
- Оптимизация доставки
- Сеть, HTTP/2, HTTP/3
- Тестирование и мониторинг
- Быстрые победы
- Все на одной странице
- Скачать контрольный список (PDF, Apple Pages, MS Word)
- Подпишитесь на нашу рассылку по электронной почте, чтобы не пропустить следующие руководства.
Оптимизация активов
- Используйте Brotli для сжатия простого текста.
В 2015 году Google представила Brotli, новый формат данных без потерь с открытым исходным кодом, который теперь поддерживается во всех современных браузерах. Библиотека Brotli с открытым исходным кодом, которая реализует кодировщик и декодер для Brotli, имеет 11 предопределенных уровней качества для кодировщика, при этом более высокий уровень качества требует больше ресурсов ЦП в обмен на лучшую степень сжатия. Более медленное сжатие в конечном итоге приведет к более высокой скорости сжатия, но тем не менее Brotli быстро распаковывает. Однако стоит отметить, что Brotli с уровнем сжатия 4 меньше и сжимает быстрее, чем Gzip.На практике Brotli оказывается намного эффективнее, чем Gzip. Мнения и опыт различаются, но если ваш сайт уже оптимизирован с помощью Gzip, вы можете ожидать, по крайней мере, однозначных улучшений и, в лучшем случае, двузначных улучшений в уменьшении размера и времени FCP. Вы также можете оценить экономию сжатия Brotli для вашего сайта.
Браузеры будут принимать Brotli, только если пользователь посещает веб-сайт через HTTPS. Brotli широко поддерживается, и многие CDN поддерживают его (Akamai, Netlify Edge, AWS, KeyCDN, Fastly (в настоящее время только как сквозной), Cloudflare, CDN77), и вы можете включить Brotli даже на CDN, которые еще не поддерживают его. (с обслуживающим персоналом).
Загвоздка в том, что, поскольку сжатие всех ресурсов с помощью Brotli при высоком уровне сжатия обходится дорого, многие хостинг-провайдеры не могут использовать его в полном объеме только из-за огромных накладных расходов, которые он создает. На самом деле, на самом высоком уровне сжатия Brotli работает настолько медленно, что любое потенциальное увеличение размера файла может быть сведено на нет из-за времени, которое требуется серверу, чтобы начать отправку ответа, поскольку он ожидает динамического сжатия ресурса. (Но если у вас есть время во время сборки со статическим сжатием, конечно, предпочтительны более высокие настройки сжатия.)
Хотя это может измениться. Формат файла Brotli включает встроенный статический словарь и, помимо того, что он содержит различные строки на нескольких языках, также поддерживает возможность применения нескольких преобразований к этим словам, что повышает его универсальность. В своем исследовании Феликс Ханау обнаружил способ улучшить сжатие на уровнях с 5 по 9, используя «более специализированное подмножество словаря, чем по умолчанию» и полагаясь на заголовок
Content-Type
, чтобы указать компрессору, следует ли ему использовать словарь для HTML, JavaScript или CSS. Результатом было «незначительное влияние на производительность (на 1-3% больше ЦП по сравнению с 12% в обычном режиме) при сжатии веб-контента на высоких уровнях сжатия с использованием подхода с ограниченным использованием словаря».Кроме того, благодаря исследованиям Елены Кириленко мы можем добиться быстрой и эффективной повторной компрессии Brotli , используя предыдущие артефакты сжатия. По словам Елены, «когда у нас есть ресурс, сжатый с помощью Brotli, и мы пытаемся сжимать динамический контент «на лету», когда контент напоминает контент, доступный нам заранее, мы можем добиться значительного улучшения времени сжатия. "
Как часто это бывает? Например, с доставкой подмножеств пакетов JavaScript (например, когда части кода уже кэшированы на клиенте или с динамическим пакетом, обслуживающим WebBundles). Или с динамическим HTML, основанным на заранее известных шаблонах, или с динамическим подмножеством шрифтов WOFF2 . По словам Елены, мы можем получить улучшение сжатия на 5,3% и улучшение скорости сжатия на 39% при удалении 10% контента, а также повышение скорости сжатия на 3,2% и ускорение сжатия на 26% при удалении 50% контента.
Сжатие Brotli становится лучше, поэтому, если вы можете обойти затраты на динамическое сжатие статических ресурсов, это определенно стоит затраченных усилий. Само собой разумеется, что Brotli можно использовать для любой полезной нагрузки открытого текста — HTML, CSS, SVG, JavaScript, JSON и так далее.
Примечание . По состоянию на начало 2021 года примерно 60 % HTTP-ответов доставляются без текстового сжатия, 30,82 % сжимаются с помощью Gzip и 9,1 % со сжатием с помощью Brotli (как на мобильных устройствах, так и на настольных компьютерах). Например, 23,4% страниц Angular не сжаты (через gzip или Brotli). Тем не менее, часто включение сжатия является одним из самых простых способов повысить производительность простым щелчком переключателя.
Стратегия? Предварительно сжимайте статические ресурсы с помощью Brotli+Gzip на самом высоком уровне и сжимайте (динамический) HTML на лету с помощью Brotli на уровне 4–6. Убедитесь, что сервер правильно обрабатывает согласование содержимого для Brotli или Gzip.
- Используем ли мы адаптивную загрузку мультимедиа и клиентские подсказки?
Это пришло из страны старых новостей, но это всегда хорошее напоминание об использовании адаптивных изображений сsrcset
,sizes
и элементом<picture>
. Специально для сайтов с большим количеством носителей мы можем сделать еще один шаг вперед с адаптивной загрузкой мультимедиа (в этом примере React + Next.js), предоставляя легкий опыт для медленных сетей и устройств с малым объемом памяти и полный опыт для быстрой сети и высокой производительности. -устройства памяти. В контексте React мы можем добиться этого с помощью клиентских подсказок на сервере и реактивных адаптивных хуков на клиенте.Будущее адаптивных изображений может резко измениться с более широким внедрением клиентских подсказок. Подсказки клиента — это поля заголовка HTTP-запроса, например,
DPR
,Viewport-Width
,Width
,Save-Data
,Accept
(для указания предпочтений формата изображения) и другие. Они должны информировать сервер об особенностях браузера пользователя, экрана, подключения и т. д.В результате сервер может решить, как заполнить макет изображениями подходящего размера , и обслуживать только эти изображения в нужных форматах. С помощью клиентских подсказок мы перемещаем выбор ресурсов из HTML-разметки в процесс согласования запроса и ответа между клиентом и сервером.
Как заметил Илья Григорик, клиентские подсказки дополняют картину — они не являются альтернативой адаптивным изображениям. «Элемент
<picture>
обеспечивает необходимое управление художественным оформлением в HTML-разметке. Подсказки клиента предоставляют аннотации к полученным запросам изображений, что позволяет автоматизировать выбор ресурсов. Service Worker предоставляет полные возможности управления запросами и ответами на клиенте».Сервисный работник может, например, добавить новые значения заголовков подсказок клиента к запросу, переписать URL-адрес и направить запрос изображения в CDN, адаптировать ответ на основе подключения и пользовательских предпочтений и т. д. Это верно не только для ресурсов изображений, но почти для всех других запросов.
Для клиентов, поддерживающих клиентские подсказки, можно было измерить 42% экономии байтов на изображениях и на 1 МБ+ меньше байтов для 70-го+ процентиля. На Smashing Magazine мы также смогли измерить улучшение на 19-32%. Клиентские подсказки поддерживаются в браузерах на основе Chromium, но в Firefox они все еще находятся на рассмотрении.
Однако если вы укажете как обычную разметку адаптивных изображений, так и
<meta>
для клиентских подсказок, поддерживающий браузер оценит разметку адаптивных изображений и запросит соответствующий источник изображения, используя HTTP-заголовки клиентских подсказок. - Используем ли мы адаптивные изображения для фоновых изображений?
Мы обязательно должны! С помощьюimage-set
, который теперь поддерживается в Safari 14 и в большинстве современных браузеров, кроме Firefox, мы также можем отображать адаптивные фоновые изображения:background-image: url("fallback.jpg"); background-image: image-set( "photo-small.jpg" 1x, "photo-large.jpg" 2x, "photo-print.jpg" 600dpi);
По сути, мы можем условно обслуживать фоновые изображения с низким разрешением с дескриптором
1x
, изображения с более высоким разрешением с дескриптором2x
и даже изображение качества печати с дескриптором600dpi
. Однако будьте осторожны: браузеры не предоставляют никакой специальной информации о фоновых изображениях вспомогательным технологиям, поэтому в идеале эти фотографии будут просто украшением. - Используем ли мы WebP?
Сжатие изображений часто считается быстрой победой, но на практике оно все еще используется недостаточно. Конечно, изображения не блокируют рендеринг, но они сильно влияют на плохие оценки LCP, и очень часто они слишком тяжелые и слишком большие для устройства, на котором они используются.Так что, по крайней мере, мы могли бы изучить использование формата WebP для наших изображений. Фактически, сага WebP близится к концу в прошлом году, когда Apple добавила поддержку WebP в Safari 14. Итак, после многих лет дискуссий и дебатов, на сегодняшний день WebP поддерживается во всех современных браузерах. Таким образом, мы можем обслуживать изображения WebP с элементом
<picture>
и запасным вариантом JPEG, если это необходимо (см. фрагмент кода Андреаса Бовенса) или с помощью согласования содержимого (используя заголовкиAccept
).Однако WebP не лишен недостатков . Несмотря на то, что размеры файла изображения WebP по сравнению с эквивалентными Guetzli и Zopfli, этот формат не поддерживает прогрессивный рендеринг, такой как JPEG, поэтому пользователи могут быстрее увидеть готовое изображение со старым добрым JPEG, хотя изображения WebP могут становиться быстрее через сеть. С JPEG мы можем обслуживать «достойный» пользовательский интерфейс с половиной или даже четвертью данных и загружать остальные позже, вместо того, чтобы иметь полупустое изображение, как в случае WebP.
Ваше решение будет зависеть от того, что вам нужно: с WebP вы уменьшите полезную нагрузку, а с JPEG вы улучшите воспринимаемую производительность. Вы можете узнать больше о WebP в выступлении Паскаля Массимино из Google.
Для преобразования в WebP вы можете использовать WebP Converter, cwebp или libwebp. У Айра Адеринокуна также есть очень подробное руководство по преобразованию изображений в WebP, как и у Джоша Комо в его статье о работе с современными форматами изображений.
Sketch изначально поддерживает WebP, а изображения WebP можно экспортировать из Photoshop с помощью подключаемого модуля WebP для Photoshop. Но возможны и другие варианты.
Если вы используете WordPress или Joomla, существуют расширения, которые помогут вам легко реализовать поддержку WebP, такие как Optimus и Cache Enabler для WordPress и собственное поддерживаемое расширение Joomla (через Коди Арсено). Вы также можете абстрагироваться от элемента
<picture>
с помощью React, стилизованных компонентов или gatsby-image.Ах — бессовестная вилка! — Джереми Вагнер даже опубликовал потрясающую книгу о WebP, с которой вы, возможно, захотите ознакомиться, если вас интересует все, что связано с WebP.
- Используем ли мы AVIF?
Возможно, вы уже слышали важные новости: AVIF приземлился. Это новый формат изображения, полученный из ключевых кадров видео AV1. Это открытый, бесплатный формат, который поддерживает сжатие с потерями и без потерь, анимацию, альфа-канал с потерями и может обрабатывать четкие линии и сплошные цвета (что было проблемой с JPEG), обеспечивая при этом лучшие результаты в обоих случаях.На самом деле, по сравнению с WebP и JPEG, AVIF работает значительно лучше , обеспечивая экономию среднего размера файла до 50% при том же DSSIM ((не)подобие между двумя или более изображениями с использованием алгоритма, близкого к человеческому зрению). На самом деле, в своем подробном посте об оптимизации загрузки изображений Мальте Убл отмечает, что AVIF «очень последовательно превосходит JPEG в очень значительном смысле. потери из-за отсутствия поддержки прогрессивной загрузки».
Как ни странно, AVIF может работать даже лучше, чем большие SVG, хотя, конечно, его не следует рассматривать как замену SVG. Это также один из первых форматов изображений, поддерживающих поддержку цвета HDR; предлагая более высокую яркость, глубину цвета и цветовую гамму. Единственным недостатком является то, что в настоящее время AVIF не поддерживает прогрессивное декодирование изображений (пока?) и, как и Brotli, кодирование с высокой степенью сжатия в настоящее время довольно медленное, хотя декодирование быстрое.
В настоящее время AVIF поддерживается в Chrome, Firefox и Opera, и ожидается, что поддержка в Safari появится в ближайшее время (поскольку Apple является членом группы, создавшей AV1).
Каков наилучший способ подачи изображений в наши дни ? Для иллюстраций и векторных изображений (сжатый) SVG, несомненно, лучший выбор. Для фотографий мы используем методы согласования контента с элементом
picture
. Если AVIF поддерживается, мы отправляем изображение AVIF; если это не так, мы сначала возвращаемся к WebP, а если WebP также не поддерживается, мы переключаемся на JPEG или PNG в качестве резерва (при необходимости применяя условия@media
):<picture> <source type="image/avif"> <source type="image/webp"> <img src="image.jpg" alt="Photo" width="450" height="350"> </picture>
Честно говоря, более вероятно, что мы будем использовать некоторые условия в элементе
picture
:<picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>
<picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>
Вы можете пойти еще дальше, заменив анимированные изображения статическими изображениями для клиентов, которые соглашаются на меньшее движение с помощью
prefers-reduced-motion
:<picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>
<picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>
За пару месяцев AVIF набрал обороты:
- Мы можем протестировать резервные варианты WebP/AVIF на панели Rendering в DevTools.
- Мы можем использовать Squoosh, AVIF.io и libavif для кодирования, декодирования, сжатия и преобразования файлов AVIF.
- Мы можем использовать компонент AVIF Preact Джейка Арчибальда, который декодирует AVIF-файл в воркере и отображает результат на холсте,
- Чтобы предоставить AVIF только поддерживающим браузерам, мы можем использовать плагин PostCSS вместе со скриптом 315B для использования AVIF в ваших объявлениях CSS.
- Мы можем постепенно предоставлять новые форматы изображений с помощью CSS и Cloudlare Workers, чтобы динамически изменять возвращаемый HTML-документ, выводя информацию из заголовка
accept
, а затем добавляяwebp/avif
и т. д. по мере необходимости. - AVIF уже доступен в Cloudinary (с ограничениями на использование), Cloudflare поддерживает AVIF при изменении размера изображения, и вы можете включить AVIF с пользовательскими заголовками AVIF в Netlify.
- Когда дело доходит до анимации, AVIF работает так же, как
<img src=mp4>
в Safari, превосходя GIF и WebP в целом, но MP4 по-прежнему работает лучше. - В общем, для анимации AVC1 (h264) > HVC1 > WebP > AVIF > GIF, при условии, что браузеры на основе Chromium когда-либо будут поддерживать
<img src=mp4>
. - Вы можете найти более подробную информацию об AVIF в AVIF for Next Generation Image Coding в докладе Адитьи Мавланкар из Netflix и в докладе Корнела Лесински из Cloudflare о формате изображения.
- Отличный справочник по всему AVIF: подробный пост Джейка Арчибальда на AVIF приземлился.
Так есть ли будущее в AVIF ? Джон Снейерс не согласен: AVIF работает на 60% хуже, чем JPEG XL, еще один бесплатный и открытый формат, разработанный Google и Cloudinary. На самом деле, JPEG XL, кажется, работает намного лучше по всем направлениям. Однако JPEG XL все еще находится на завершающей стадии стандартизации и еще не работает ни в одном браузере. (Не путать с JPEG-XR от Microsoft, исходящим из старого доброго Internet Explorer 9 раз).
- Правильно ли оптимизированы JPEG/PNG/SVG?
Когда вы работаете над целевой страницей, на которой очень важно, чтобы главное изображение загружалось молниеносно быстро, убедитесь, что файлы JPEG являются прогрессивными и сжаты с помощью mozJPEG (который сокращает время начального рендеринга за счет управления уровнями сканирования) или Guetzli, Google с открытым исходным кодом. кодировщик, ориентированный на производительность восприятия и использующий знания Zopfli и WebP. Единственный недостаток: медленное время обработки (минута процессора на мегапиксель).Для PNG мы можем использовать Pingo, а для SVG мы можем использовать SVGO или SVGOMG. И если вам нужно быстро просмотреть и скопировать или загрузить все ресурсы SVG с веб-сайта, svg-grabber может сделать это за вас.
Об этом говорится в каждой статье по оптимизации изображений, но всегда стоит упомянуть о чистоте и аккуратности векторных ресурсов. Обязательно очистите неиспользуемые активы, удалите ненужные метаданные и уменьшите количество точек пути в иллюстрации (и, следовательно, в коде SVG). ( Спасибо, Джереми! )
Однако есть и полезные онлайн-инструменты:
- Используйте Squoosh для сжатия, изменения размера и управления изображениями с оптимальным уровнем сжатия (с потерями или без потерь),
- Используйте Guetzli.it для сжатия и оптимизации изображений JPEG с помощью Guetzli, который хорошо работает с изображениями с четкими краями и сплошными цветами (но может быть немного медленнее)).
- Используйте Генератор контрольных точек адаптивного изображения или такой сервис, как Cloudinary или Imgix, для автоматизации оптимизации изображения. Кроме того, во многих случаях использование
srcset
иsizes
дает значительные преимущества. - Чтобы проверить эффективность вашей адаптивной разметки, вы можете использовать images-heap, инструмент командной строки, который измеряет эффективность в зависимости от размера окна просмотра и соотношения пикселей устройства.
- Вы можете добавить автоматическое сжатие изображений в свои рабочие процессы GitHub, чтобы ни одно изображение не попадало в рабочую среду без сжатия. Экшен использует mozjpeg и libvips, которые работают с PNG и JPG.
- Чтобы оптимизировать внутреннюю память, вы можете использовать новый формат Dropbox Lepton для сжатия файлов JPEG без потерь в среднем на 22%.
- Используйте BlurHash, если вы хотите показать замещающее изображение заранее. BlurHash берет изображение и дает вам короткую строку (всего 20-30 символов!), которая представляет собой заполнитель для этого изображения. Строка достаточно короткая, чтобы ее можно было легко добавить как поле в объект JSON.
Иногда оптимизация изображений сама по себе не помогает. Чтобы сократить время, необходимое для запуска рендеринга важного изображения, отложите загрузку менее важных изображений и отложите загрузку любых скриптов после того, как критические изображения уже отрендерены. Наиболее надежным способом является гибридная отложенная загрузка, когда мы используем нативную отложенную загрузку и отложенную загрузку, библиотеку, которая обнаруживает любые изменения видимости, вызванные взаимодействием с пользователем (с помощью IntersectionObserver, который мы рассмотрим позже). Кроме того:
- Рассмотрите возможность предварительной загрузки важных изображений, чтобы браузер не обнаружил их слишком поздно. Для фоновых изображений, если вы хотите быть еще более агрессивным, вы можете добавить изображение как обычное изображение с помощью
<img src>
, а затем скрыть его с экрана. - Рассмотрите возможность замены изображений с помощью атрибута Sizes, указав различные размеры отображения изображения в зависимости от медиа-запросов, например, чтобы управлять
sizes
для замены источников в компоненте лупы. - Проверьте несоответствия загрузки изображений, чтобы предотвратить неожиданную загрузку изображений переднего плана и фона. Следите за изображениями, которые загружаются по умолчанию, но могут никогда не отображаться — например, в каруселях, аккордеонах и галереях изображений.
- Всегда устанавливайте
width
иheight
изображений. Обратите внимание на свойствоaspect-ratio
в CSS и атрибутintrinsicsize
размера, который позволит нам устанавливать пропорции и размеры для изображений, чтобы браузер мог заранее зарезервировать заранее определенный слот макета, чтобы избежать скачков макета во время загрузки страницы.
Если вы чувствуете себя предприимчивым, вы можете обрезать и переупорядочивать потоки HTTP/2, используя Edge Workers, в основном фильтр в реальном времени, живущий в CDN, для более быстрой отправки изображений по сети. Пограничные рабочие используют потоки JavaScript, которые используют фрагменты, которыми вы можете управлять (по сути, это JavaScript, работающий на краю CDN, который может изменять потоковые ответы), поэтому вы можете контролировать доставку изображений.
С сервис-воркером уже слишком поздно, так как вы не можете контролировать то, что передается по сети, но он работает с пограничными работниками. Таким образом, вы можете использовать их поверх статических файлов JPEG, постепенно сохраняемых для конкретной целевой страницы.
Не достаточно хорош? Что ж, вы также можете улучшить воспринимаемую производительность для изображений с помощью метода множественных фоновых изображений. Имейте в виду, что игра с контрастом и размытие ненужных деталей (или удаление цветов) также могут уменьшить размер файла. Ах, вам нужно увеличить маленькое фото без потери качества? Рассмотрите возможность использования Letsenhance.io.
Эти оптимизации пока охватывают только основы. Эдди Османи опубликовала очень подробное руководство по Essential Image Optimization, в котором подробно рассказывается о сжатии изображений и управлении цветом. Например, вы можете размыть ненужные части изображения (применив к ним фильтр размытия по Гауссу), чтобы уменьшить размер файла, и в конечном итоге вы можете даже начать удалять цвета или превратить изображение в черно-белое, чтобы еще больше уменьшить размер. . Для фоновых изображений экспорт фотографий из Photoshop с качеством от 0 до 10% также может быть абсолютно приемлемым.
В Smashing Magazine мы используем постфикс
-opt
для имен изображений — например,brotli-compression-opt.png
; всякий раз, когда изображение содержит этот постфикс, все в команде знают, что изображение уже оптимизировано.Ах, и не используйте JPEG-XR в Интернете — «обработка декодирования JPEG-XR на стороне программного обеспечения на ЦП сводит на нет и даже перевешивает потенциально положительное влияние экономии размера байта, особенно в контексте SPA» (не чтобы перепутать с Cloudinary / Google JPEG XL).
- Правильно ли оптимизированы видео?
До сих пор мы рассматривали изображения, но избегали разговоров о старых добрых GIF-файлах. Несмотря на нашу любовь к GIF, пришло время отказаться от них навсегда (по крайней мере, в наших веб-сайтах и приложениях). Вместо того, чтобы загружать тяжелые анимированные GIF-файлы, которые влияют как на производительность рендеринга, так и на пропускную способность, рекомендуется переключиться либо на анимированный WebP (где GIF является запасным вариантом), либо полностью заменить их зацикленными видео HTML5.В отличие от изображений, браузеры не загружают предварительно содержимое
<video>
, но видео HTML5, как правило, намного легче и меньше, чем GIF. Не вариант? Ну, по крайней мере, мы можем добавить сжатие с потерями к GIF с помощью Lossy GIF, gifsicle или giflossy.Тесты, проведенные Колином Бенделлом, показывают, что встроенные видео в тегах
img
в Safari Technology Preview отображаются по крайней мере в 20 раз быстрее и декодируются в 7 раз быстрее, чем эквивалент GIF, в дополнение к тому, что они имеют меньший размер файла. Однако он не поддерживается в других браузерах.В стране хороших новостей форматы видео стремительно развиваются на протяжении многих лет. Долгое время мы надеялись, что WebM станет форматом, который будет управлять ими всеми, а WebP (который, по сути, представляет собой одно неподвижное изображение внутри видеоконтейнера WebM) станет заменой устаревшим форматам изображений. Действительно, Safari теперь поддерживает WebP, но, несмотря на то, что WebP и WebM получили поддержку в наши дни, прорыва на самом деле не произошло.
Тем не менее, мы могли бы использовать WebM для большинства современных браузеров:
<!-- By Houssein Djirdeh. https://web.dev/replace-gifs-with-videos/ --> <!-- A common scenartio: MP4 with a WEBM fallback. --> <video autoplay loop muted playsinline> <source src="my-animation.webm" type="video/webm"> <source src="my-animation.mp4" type="video/mp4"> </video>
Но, возможно, мы могли бы вернуться к нему вообще. В 2018 году Альянс открытых медиа выпустил новый перспективный формат видео под названием AV1 . AV1 имеет сжатие, аналогичное кодеку H.265 (эволюция H.264), но в отличие от последнего, AV1 является бесплатным. Стоимость лицензии H.265 подтолкнула поставщиков браузеров к использованию вместо этого сравнительно производительного AV1: AV1 (точно так же, как H.265) сжимает в два раза лучше, чем WebM .
На самом деле Apple в настоящее время использует формат HEIF и HEVC (H.265), и все фото и видео на последней версии iOS сохраняются в этих форматах, а не в JPEG. В то время как HEIF и HEVC (H.265) не доступны должным образом в Интернете (пока?), AV1 — и получает поддержку браузеров. Поэтому добавление источника
AV1
в ваш<video>
разумно, так как все поставщики браузеров, похоже, согласны с этим.На данный момент наиболее широко используемой и поддерживаемой кодировкой является H.264, обслуживаемая файлами MP4, поэтому перед подачей файла убедитесь, что ваши MP4-файлы обработаны многопроходным кодированием, размыты эффектом frei0r iirblur (если применимо) и Метаданные атома moov перемещаются в заголовок файла, в то время как ваш сервер принимает обслуживание байтов. Борис Шапира дает точные инструкции для FFmpeg по максимальной оптимизации видео. Конечно, предоставление формата WebM в качестве альтернативы тоже помогло бы.
Нужно ускорить рендеринг видео, но видеофайлы все еще слишком велики ? Например, когда у вас есть большое фоновое видео на целевой странице? Обычный метод заключается в том, чтобы сначала показать самый первый кадр в виде неподвижного изображения или отобразить сильно оптимизированный короткий зацикленный сегмент, который можно интерпретировать как часть видео, а затем, когда видео будет достаточно буферизовано, начать воспроизведение. собственно видео. Дуг Силларс написал подробное руководство по производительности фонового видео, которое может быть полезно в этом случае. ( Спасибо, Гай Поджарный! ).
Для приведенного выше сценария вы можете предоставить адаптивные изображения постеров . По умолчанию элементы
video
позволяют использовать только одно изображение в качестве постера, что не всегда оптимально. Мы можем использовать Responsive Video Poster, библиотеку JavaScript, которая позволяет использовать разные изображения постеров для разных экранов, а также добавлять переходное наложение и полный контроль над стилем заполнителей видео.Исследование показывает, что качество видеопотока влияет на поведение зрителей. На самом деле зрители начинают отказываться от видео, если задержка запуска превышает примерно 2 секунды. После этого увеличение задержки на 1 секунду приводит к увеличению процента отказов примерно на 5,8%. Поэтому неудивительно, что среднее время начала видео составляет 12,8 с, при этом 40% видео имеют по крайней мере 1 остановку, а 20% - по крайней мере 2 секунды воспроизведения видео. На самом деле, зависания видео неизбежны в 3G, поскольку видео воспроизводится быстрее, чем сеть может предоставить контент.
Итак, каково решение? Обычно устройства с небольшим экраном не могут обрабатывать 720p и 1080p, которые мы обслуживаем на рабочем столе. По словам Дуга Силларса, мы можем либо создавать уменьшенные версии наших видео, либо использовать Javascript для определения источника для небольших экранов, чтобы обеспечить быстрое и плавное воспроизведение на этих устройствах. В качестве альтернативы мы можем использовать потоковое видео. Видеопотоки HLS будут доставлять на устройство видео соответствующего размера, что избавляет от необходимости создавать разные видео для разных экранов. Он также согласует скорость сети и адаптирует битрейт видео к скорости используемой вами сети.
Чтобы избежать потери полосы пропускания, мы могли добавить источник видео только для устройств, которые действительно могут хорошо воспроизводить видео. В качестве альтернативы мы можем вообще удалить
autoplay
из тегаvideo
и использовать JavaScript для вставкиautoplay
для больших экранов. Кроме того, нам нужно добавитьpreload="none"
кvideo
, чтобы указать браузеру не загружать какие -либо видеофайлы, пока он действительно не понадобится:<!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>
Затем мы можем настроить таргетинг на браузеры, которые действительно поддерживают AV1:
<!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.av1.mp4" type="video/mp4; codecs=av01.0.05M.08"> <source src="video.hevc.mp4" type="video/mp4; codecs=hevc"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>
Затем мы могли бы повторно добавить
autoplay
выше определенного порога (например, 1000 пикселей):/* By Doug Sillars. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ */ <script> window.onload = addAutoplay(); var videoLocation = document.getElementById("hero-video"); function addAutoplay() { if(window.innerWidth > 1000){ videoLocation.setAttribute("autoplay",""); }; } </script>
Производительность воспроизведения видео — это отдельная история, и если вы хотите погрузиться в нее подробнее, взгляните на другую серию статей Дуга Силларса «Текущее состояние видео и лучшие практики доставки видео», в которой подробно описаны показатели доставки видео. , предварительная загрузка видео, сжатие и потоковая передача. Наконец, вы можете проверить, насколько медленным или быстрым будет ваше потоковое видео с помощью Stream or Not.
- Оптимизирована ли доставка веб-шрифтов?
Первый вопрос, который стоит задать, заключается в том, можем ли мы вообще обойтись без использования системных шрифтов пользовательского интерфейса — нам просто нужно дважды проверить, правильно ли они отображаются на разных платформах. Если это не так, высока вероятность того, что веб-шрифты, которые мы обслуживаем, содержат глифы и дополнительные функции и веса, которые не используются. Мы можем попросить нашу компанию создать подмножество веб-шрифтов или, если мы используем шрифты с открытым исходным кодом, подмножить их самостоятельно с помощью Glyphhanger или Fontsquirrel. Мы даже можем автоматизировать весь наш рабочий процесс с помощью подшрифта Питера Мюллера, инструмента командной строки, который статически анализирует вашу страницу, чтобы создать наиболее оптимальные наборы веб-шрифтов, а затем внедрить их на наши страницы.Поддержка WOFF2 великолепна, и мы можем использовать WOFF в качестве запасного варианта для браузеров, которые его не поддерживают — или, возможно, устаревшие браузеры могут обслуживаться системными шрифтами. Существует много-много вариантов загрузки веб-шрифтов, и мы можем выбрать одну из стратегий из «Всеобъемлющего руководства по стратегиям загрузки шрифтов» Зака Лезермана (фрагменты кода также доступны в виде рецептов загрузки веб-шрифтов).
Вероятно, лучшими вариантами для рассмотрения сегодня являются критический FOFT с
preload
загрузкой и метод «Компромисс». Оба они используют двухэтапный рендеринг для поэтапной доставки веб-шрифтов — сначала небольшой надмножество, необходимое для быстрого и точного рендеринга страницы с помощью веб-шрифта, а затем асинхронная загрузка остальной части семейства. Разница в том, что метод «Компромисс» загружает полифилл асинхронно, только если события загрузки шрифта не поддерживаются, поэтому вам не нужно загружать полифилл по умолчанию. Нужна быстрая победа? У Zach Leatherman есть краткое 23-минутное руководство и тематическое исследование, чтобы привести шрифты в порядок.В общем, может быть хорошей идеей использовать подсказку ресурса
preload
для предварительной загрузки шрифтов, но в вашей разметке включите подсказки после ссылки на важные CSS и JavaScript. Сpreload
возникает головоломка с приоритетами, поэтому рассмотрите возможность внедрения элементовrel="preload"
в DOM непосредственно перед внешними блокирующими сценариями. По словам Энди Дэвиса, «ресурсы, внедренные с помощью скрипта, скрыты от браузера до тех пор, пока скрипт не выполнится, и мы можем использовать это поведение, чтобы отложить, когда браузер обнаружит подсказкуpreload
». В противном случае загрузка шрифта обойдется вам в первое время рендеринга.Это хорошая идея, чтобы быть избирательным и выбирать файлы, которые наиболее важны, например, те, которые имеют решающее значение для рендеринга или которые помогут вам избежать видимых и разрушительных перекомпоновок текста. Вообще Зак советует предварительно загружать один-два шрифта каждого семейства — также есть смысл отложить загрузку некоторых шрифтов, если они менее критичны.
Стало довольно распространенным использовать значение
local()
(которое относится к локальному шрифту по имени) при определенииfont-family
шрифтов в правиле@font-face
:/* Warning! Not a good idea! */ @font-face { font-family: Open Sans; src: local('Open Sans Regular'), local('OpenSans-Regular'), url('opensans.woff2') format ('woff2'), url('opensans.woff') format('woff'); }
Идея разумна: некоторые популярные шрифты с открытым исходным кодом, такие как Open Sans, поставляются с предустановленными драйверами или приложениями, поэтому, если шрифт доступен локально, браузеру не нужно загружать веб-шрифт, и он может отображать локальный шрифт. шрифт сразу. Как заметил Брэм Стейн, «хотя локальный шрифт совпадает с названием веб-шрифта, скорее всего , это не тот же самый шрифт . Многие веб-шрифты отличаются от их «настольной» версии. Текст может отображаться по-разному, некоторые символы могут вернуться к другим шрифтам, функции OpenType могут полностью отсутствовать или высота строки может быть другой».
Кроме того, поскольку шрифты со временем развиваются, локально установленная версия может сильно отличаться от веб-шрифта, а символы выглядят совсем иначе. Итак, по словам Брэма, лучше никогда не смешивать локально установленные шрифты и веб-шрифты в правилах
@font-face
. Google Fonts последовал этому примеру, отключивlocal()
в результатах CSS для всех пользователей, кроме запросов Android для Roboto.Никто не любит ждать, пока контент будет отображен. С помощью CSS-дескриптора
font-display
мы можем управлять поведением при загрузке шрифта и сделать содержимое доступным для чтения немедленно (с помощьюfont-display: optional
) или почти сразу (с тайм-аутом 3 с, пока шрифт успешно загружен — с помощьюfont-display: swap
). (Ну, это немного сложнее, чем это.)Однако, если вы хотите свести к минимуму влияние перекомпоновки текста, мы могли бы использовать API загрузки шрифтов (поддерживается во всех современных браузерах). В частности, это означает, что для каждого шрифта мы создадим объект
FontFace
, затем попытаемся получить их все и только потом применить к странице. Таким образом, мы группируем все перерисовки , загружая все шрифты асинхронно, а затем переключаемся с резервных шрифтов на веб-шрифт ровно один раз. Взгляните на объяснение Зака, начиная с 32:15, и фрагмент кода):/* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));
/* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));
Чтобы инициировать очень раннюю загрузку шрифтов с использованием API загрузки шрифтов, Адриан Бесе предлагает добавить неразрывный пробел
nbsp;
в верхней частиbody
и визуально скройте его с помощьюaria-visibility: hidden
и класса.hidden
:<body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>
<body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>
Это соответствует CSS, в котором разные семейства шрифтов объявлены для разных состояний загрузки, с изменением, инициируемым API загрузки шрифтов после успешной загрузки шрифтов:
body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }
body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }
Если вы когда-нибудь задумывались, почему, несмотря на все ваши оптимизации, Lighthouse по-прежнему предлагает исключить ресурсы, блокирующие рендеринг (шрифты), в той же статье Адриан Бесе предлагает несколько методов, чтобы сделать Lighthouse счастливым, а также Gatsby Omni Font Loader, производительный асинхронный шрифт. Плагин загрузки и обработки Flash Of Unstyled Text (FOUT) для Gatsby.
Теперь многие из нас могут использовать CDN или сторонний хост для загрузки веб-шрифтов. В общем, всегда лучше самостоятельно размещать все свои статические ресурсы, если можете, поэтому рассмотрите возможность использования google-webfonts-helper, простого способа самостоятельного размещения шрифтов Google. И если это невозможно, вы можете проксировать файлы шрифтов Google через источник страницы.
Однако стоит отметить, что Google выполняет довольно много работы «из коробки», поэтому серверу может потребоваться небольшая настройка, чтобы избежать задержек ( спасибо, Барри! )
Это очень важно, особенно с учетом того, что начиная с версии Chrome v86 (выпущенной в октябре 2020 г.) межсайтовые ресурсы, такие как шрифты, больше не могут совместно использоваться в одной CDN из-за секционированного кеша браузера. Такое поведение было по умолчанию в Safari в течение многих лет.
Но если это вообще невозможно, есть способ получить максимально быстрые шрифты Google с помощью фрагмента кода Гарри Робертса:
<!-- By Harry Roberts. https://csswizardry.com/2020/05/the-fastest-google-fonts/ - 1. Preemptively warm up the fonts' origin. - 2. Initiate a high-priority, asynchronous fetch for the CSS file. Works in - most modern browsers. - 3. Initiate a low-priority, asynchronous fetch that gets applied to the page - only after it's arrived. Works in all browsers with JavaScript enabled. - 4. In the unlikely event that a visitor has intentionally disabled - JavaScript, fall back to the original method. The good news is that, - although this is a render-blocking request, it can still make use of the - preconnect which makes it marginally faster than the default. --> <!-- [1] --> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <!-- [2] --> <link rel="preload" as="style" href="$CSS&display=swap" /> <!-- [3] --> <link rel="stylesheet" href="$CSS&display=swap" media="print" onload="this.media='all'" /> <!-- [4] --> <noscript> <link rel="stylesheet" href="$CSS&display=swap" /> </noscript>
Стратегия Гарри состоит в том, чтобы сначала заранее прогреть происхождение шрифтов. Затем мы инициируем высокоприоритетную асинхронную выборку файла CSS. После этого мы инициируем низкоприоритетную асинхронную выборку, которая применяется к странице только после ее поступления (с помощью трюка с таблицей стилей печати). Наконец, если JavaScript не поддерживается, мы возвращаемся к исходному методу.
Ах, говоря о Google Fonts: вы можете сократить размер запросов Google Fonts до 90% , объявив только нужные вам символы с помощью
&text
. Кроме того, недавно в Google Fonts была добавлена поддержка отображения шрифтов, так что мы можем использовать ее из коробки.Однако небольшое предостережение. Если вы используете
font-display: optional
, использованиеpreload
может быть неоптимальным, так как это вызовет ранний запрос веб-шрифта (вызывая перегрузку сети , если у вас есть другие ресурсы критического пути, которые необходимо извлечь). Используйтеpreconnect
для более быстрых запросов шрифтов из разных источников, но будьте осторожны сpreload
загрузкой, так как предварительная загрузка шрифтов из другого источника вызовет конкуренцию в сети. Все эти приемы описаны в рецептах загрузки веб-шрифтов Зака.С другой стороны, может быть хорошей идеей отказаться от веб-шрифтов (или, по крайней мере, рендеринга второго этапа), если пользователь включил функцию «Уменьшение движения» в настройках специальных возможностей или выбрал режим экономии данных (см. заголовок «
Save-Data
»). , или когда у пользователя медленное подключение (через Network Information API).Мы также можем использовать медиа-запрос
prefers-reduced-data
CSS, чтобы не определять объявления шрифтов, если пользователь выбрал режим сохранения данных (есть и другие варианты использования). Медиа-запрос в основном раскрывает, включен или выключен заголовок запросаSave-Data
из HTTP-расширения Client Hint, чтобы разрешить использование с CSS. В настоящее время поддерживается только в Chrome и Edge.Метрики? Чтобы измерить производительность загрузки веб-шрифтов, рассмотрите метрику « Видимый весь текст » (момент, когда все шрифты загружены и весь контент отображается в веб-шрифтах), время до реального курсива, а также счетчик перекомпоновки веб-шрифтов после первого рендеринга. Очевидно, что чем ниже обе метрики, тем выше производительность.
А как насчет вариативных шрифтов , спросите вы? Важно отметить, что вариативные шрифты могут потребовать значительного внимания к производительности. Они дают нам гораздо более широкое дизайнерское пространство для выбора типографики, но это происходит за счет одного последовательного запроса, а не нескольких запросов отдельных файлов.
В то время как вариативные шрифты резко уменьшают общий объединенный размер файлов шрифтов, один запрос может быть медленным, блокируя отрисовку всего содержимого на странице. Таким образом, подмножество и разделение шрифта на наборы символов по-прежнему имеют значение. С хорошей стороны, однако, с переменным шрифтом мы получим ровно одно переформатирование по умолчанию, поэтому для группировки перерисовок не потребуется JavaScript.
Итак, что тогда может сделать пуленепробиваемую стратегию загрузки веб-шрифтов ? Подмножьте шрифты и подготовьте их к двухэтапному рендерингу, объявите их с помощью дескриптора
font-display
шрифтов, используйте API загрузки шрифтов для группировки перерисовок и сохранения шрифтов в постоянном кэше сервисного работника. При первом посещении введите предварительную загрузку скриптов непосредственно перед блокировкой внешних скриптов. При необходимости вы можете вернуться к Font Face Observer Брэма Штейна. А если вам интересно измерить производительность загрузки шрифтов, Андреас Маршке исследует отслеживание производительности с помощью Font API и UserTiming API.Наконец, не забудьте включить
unicode-range
, чтобы разбить большой шрифт на более мелкие шрифты для конкретного языка, и использовать сопоставитель стиля шрифта Моники Динкулеску, чтобы свести к минимуму резкое изменение макета из-за несоответствия размеров между запасным и исходным шрифтами. веб-шрифты.В качестве альтернативы, чтобы эмулировать веб-шрифт для резервного шрифта, мы можем использовать дескрипторы @font-face для переопределения метрик шрифта (демонстрация, включена в Chrome 87). (Обратите внимание, что настройки сложны со сложными стеками шрифтов.)
Будущее выглядит светлым? С прогрессивным обогащением шрифта в конечном итоге мы сможем «загружать только необходимую часть шрифта на любой данной странице, а для последующих запросов на этот шрифт динамически« исправлять »исходную загрузку с дополнительными наборами глифов по мере необходимости на последующей странице. просмотров», как объясняет Джейсон Паменталь. Демо-версия Incremental Transfer уже доступна, и работа над ней продолжается.
Оглавление
- Подготовка: планирование и показатели
- Постановка реалистичных целей
- Определение среды
- Оптимизация активов
- Оптимизация сборки
- Оптимизация доставки
- Сеть, HTTP/2, HTTP/3
- Тестирование и мониторинг
- Быстрые победы
- Все на одной странице
- Скачать контрольный список (PDF, Apple Pages, MS Word)
- Подпишитесь на нашу рассылку по электронной почте, чтобы не пропустить следующие руководства.