Оптимизация загрузки ресурсов с помощью Fetch Priority API

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

Адди Османи
Адди Османи
Лина Сохони
Лина Сохони
Патрик Минан
Патрик Минан
Барри Поллард
Барри Поллард

Поддержка браузера

  • 102
  • 102
  • Икс
  • 17.2

Источник

Когда браузер анализирует веб-страницу и начинает обнаруживать и загружать ресурсы, такие как изображения, сценарии или CSS, он назначает им priority выборки, пытаясь загрузить ресурсы в оптимальном порядке. Эти приоритеты могут зависеть от типа ресурса и места его расположения в документе. Например, изображения в области просмотра могут иметь High приоритет, в то время как приоритет для ранней загрузки CSS, блокирующей рендеринг через <link> в <head> , может быть Very High . Браузеры довольно хорошо распределяют приоритеты, которые работают хорошо, но не во всех случаях могут быть оптимальными.

В этой статье мы обсудим API-интерфейс Fetch Priority и HTML-атрибут fetchpriority , которые позволяют указать относительный приоритет ресурса ( high или low ). Приоритет выборки может помочь оптимизировать основные веб-показатели.

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

Несколько ключевых областей, в которых может помочь функция Fetch Priority:

  • Повысьте приоритет изображения LCP, указав fetchpriority="high" в элементе изображения, что приведет к более быстрому выполнению LCP.
  • Увеличьте приоритет async сценариев, используя лучшую семантику, чем обычно используемый текущий хак (вставка <link rel="preload"> для async сценария).
  • Уменьшите приоритет скриптов позднего тела, чтобы обеспечить лучшую последовательность изображений.
Диафильм, сравнивающий два теста главной страницы Google Flights. Внизу Fetch Priority используется для повышения приоритета главного изображения, что приводит к уменьшению LCP на 0,7 секунды.
Приоритет выборки улучшает время самой большой отрисовки контента с 2,6 до 1,9 с в тесте Google Flights.

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

Fetch Priority — это сигнал на основе разметки (доступный через атрибут fetchpriority ), который разработчики могут использовать для указания относительного приоритета определенного ресурса. Вы также можете использовать эти подсказки через JavaScript и Fetch API со свойством priority , чтобы влиять на приоритет выборки ресурсов, выполняемых для данных. Приоритет выборки также может дополнять предварительную загрузку. Возьмите самое большое содержательное изображение Paint, которое при предварительной загрузке все равно будет иметь низкий приоритет. Если его оттесняют другие ранние ресурсы с низким приоритетом, использование приоритета выборки может помочь ускорить загрузку изображения.

Приоритет выборки доступен в Chrome 101 и более поздних версиях.

Приоритет ресурса

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

  • CSS, шрифтам, скриптам, изображениям и сторонним ресурсам назначаются разные приоритеты.
  • Расположение или порядок ссылки на ресурсы в документе также влияет на приоритет ресурсов.
  • Подсказка о preload ресурса помогает браузеру быстрее обнаружить ресурс и, таким образом, загрузить его до того, как документ загрузит его, и влияет на приоритет.
  • Изменения приоритета вычислений для async или defer сценариев.

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

Загрузка на этапе блокировки макета Загружайте по одному на этапе блокировки макета.
Мигать
Приоритет
Очень высоко Высокий Середина Низкий Очень низкий
Инструменты разработчика
Приоритет
Наибольший Высокий Середина Низкий Самый низкий
Основной ресурс
CSS (ранний**) CSS (поздно**) CSS (несоответствие медиа***)
Скрипт (ранний** или нет из сканера предварительной загрузки) Сценарий (поздно**) Скрипт (асинхронный)
Шрифт Шрифт (rel=предварительная загрузка)
Импортировать
Изображение (в окне просмотра) Изображение (первые 5 изображений > 10 000 пикселей2) Изображение
СМИ
SVG-документ
Предварительная выборка
XSL
XHR (синхронизация) XHR/выборка* (асинхронный)

Браузер загружает ресурсы с одинаковым вычисленным приоритетом в порядке их обнаружения. Вы можете проверить приоритет, назначенный различным ресурсам, при загрузке страницы на вкладке « Сеть инструментов разработчика Chrome». (Убедитесь, что вы включили столбец приоритета, щелкнув правой кнопкой мыши заголовки таблицы).

Скриншот ресурсов, перечисленных на вкладке «Сеть» инструментов разработчика Chrome. В столбцах слева направо указано имя, статус, тип, инициатор, размер, время и приоритет.
Приоритет для type = "font" на странице сведений о новостях BBC
Скриншот ресурсов, перечисленных на вкладке «Сеть» инструментов разработчика Chrome. В столбцах слева направо указано имя, статус, тип, инициатор, размер, время и приоритет.
Приоритет для типа ресурса = «сценарий» на странице сведений о новостях BBC.

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

Скриншот ресурсов, перечисленных на вкладке «Сеть» инструментов разработчика Chrome. Параметр «Большие строки запроса» отмечен галочкой, а в столбце «Приоритет» отображается первое изображение с приоритетом «Высокий» и другим начальным приоритетом «Средний» ниже. То же самое показано во всплывающей подсказке.
Просмотр начального и конечного приоритета в DevTools

Когда вам понадобится приоритет выборки?

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

  1. Разместите теги ресурсов, такие как <script> и <link> в зависимости от порядка их загрузки. Ресурсы с одинаковым приоритетом обычно загружаются в порядке их обнаружения.
  2. Используйте подсказку о preload ресурсов , чтобы загрузить необходимые ресурсы раньше, особенно для ресурсов, которые браузеру нелегко обнаружить на ранней стадии.
  3. Используйте async или defer загрузку скриптов, не блокируя другие ресурсы.
  4. Ленивая загрузка содержимого нижней части страницы, чтобы браузер мог использовать доступную пропускную способность для более важных ресурсов верхней части страницы.

Эти методы помогают контролировать вычисления приоритетов браузера, тем самым повышая производительность и основные веб-показатели . Например, когда критическое фоновое изображение предварительно загружено, его можно обнаружить гораздо раньше, что улучшает функцию Largest Contentful Paint ( LCP ).

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

  1. У вас есть несколько изображений в верхней части сгиба, но не обязательно, чтобы все они имели одинаковый приоритет. Например, в карусели изображений только первое видимое изображение должно иметь более высокий приоритет по сравнению с остальными.
  2. Главные изображения внутри области просмотра обычно начинаются с «Низкого» приоритета (обратите внимание, что изменение в Chrome 117 устанавливает для первых пяти больших изображений «Средний», но это может включать или не включать ваше главное изображение). После завершения макета Chrome обнаруживает, что они находятся в области просмотра, и повышает их приоритет. Обычно это приводит к значительной задержке загрузки изображения. Предоставление приоритета выборки в разметке позволяет изображению начинаться с «высокого» приоритета и начинать загрузку намного раньше.

    Обратите внимание, что предварительная загрузка по-прежнему требуется для раннего обнаружения изображений LCP, включенных в качестве фона CSS, и ее можно объединить с приоритетом выборки, включив в предварительную загрузку fetchpriority='high' , в противном случае она все равно начнется с «Низкого» или «Среднего». приоритет изображений.
  3. Объявление сценариев как async или defer указывает браузеру загружать их асинхронно. Однако, как видно из предыдущей таблицы , этим сценариям также присвоен «низкий» приоритет. Возможно, вы захотите повысить их приоритет, обеспечив при этом асинхронную загрузку, особенно для любых сценариев, которые имеют решающее значение для взаимодействия с пользователем.
  4. Вы можете использовать API JavaScript fetch() для асинхронной выборки ресурсов или данных. Браузер присваивает Fetch «высокий» приоритет. Могут возникнуть ситуации, когда вы не хотите, чтобы все ваши выборки выполнялись с «высоким» приоритетом, и предпочитаете вместо этого использовать другой приоритет выборки. Это может быть полезно при запуске фоновых вызовов API и смешивании их с вызовами API, которые реагируют на ввод пользователя, например, при автозаполнении. Фоновым вызовам API можно пометить «низкий» приоритет, а интерактивным вызовам API — «высокий».
  5. Браузер назначает CSS и шрифтам «высокий» приоритет, но не все такие ресурсы могут быть одинаково важны или необходимы для LCP. Вы можете использовать приоритет выборки, чтобы снизить приоритет некоторых из этих ресурсов.

Атрибут fetchpriority

Вы можете указать приоритет выборки, используя HTML-атрибут fetchpriority . Вы можете использовать атрибут с тегами link , img и script . Атрибут позволяет указать приоритет для типов ресурсов, таких как CSS, шрифты, скрипты и изображения, при загрузке с использованием поддерживаемых тегов. Атрибут fetchpriority принимает одно из трех значений:

  • high : вы считаете ресурс высокоприоритетным и хотите, чтобы браузер установил для него приоритет, если эвристика браузера не препятствует этому.
  • low : вы считаете ресурс низким приоритетом и хотите, чтобы браузер лишил его приоритета, если это позволяет его эвристика.
  • auto : это значение по умолчанию, при котором у вас нет предпочтений, и браузер сам определяет соответствующий приоритет.

Вот несколько примеров использования атрибута fetchpriority в разметке и свойства priority , эквивалентного сценарию.

<!-- We don't want a high priority for this above-the-fold image -->
<img src="/images/in_viewport_but_not_important.svg" fetchpriority="low" alt="I'm an unimportant image!">

<!-- We want to initiate an early fetch for a resource, but also deprioritize it -->
<link rel="preload" href="/js/script.js" as="script" fetchpriority="low">

<script>
  fetch('https://example.com/', {priority: 'low'})
  .then(data => {
    // Trigger a low priority fetch
  });
</script>

Приоритет браузера и fetchpriority

Вы можете применить атрибут fetchpriority к различным ресурсам, как показано на следующем рисунке, чтобы потенциально увеличить или уменьшить их вычисляемый приоритет. fetchpriority="auto" (◉) в каждой строке обозначает приоритет по умолчанию для этого типа ресурса (также доступен в виде документа Google ).

Загрузка на этапе блокировки макета Загружайте по одному на этапе блокировки макета.
Мигать
Приоритет
Очень высоко Высокий Середина Низкий Очень низкий
Инструменты разработчика
Приоритет
Наибольший Высокий Середина Низкий Самый низкий
Основной ресурс
CSS (ранний**) ⬆◉
CSS (поздно**)
CSS (несоответствие медиа***) ⬆*** ◉⬇
Скрипт (ранний** или нет из сканера предварительной загрузки) ⬆◉
Сценарий (поздно**)
Скрипт (асинхронный/отложенный) ◉⬇
Шрифт
Шрифт (rel=предварительная загрузка) ⬆◉
Импортировать
Изображение (во вьюпорте – после макета) ⬆◉
Изображение (первые 5 изображений > 10 000 пикселей2)
Изображение ◉⬇
Медиа (видео/аудио) ◉⬇
SVG-документ ◉⬇
XHR (синхронизация) – устаревший.
XHR/выборка* (асинхронный) ⬆◉
Предварительная выборка
XSL

Обратите внимание, что fetchpriority устанавливает относительный приоритет — то есть он повышает или понижает приоритет по умолчанию на соответствующую величину, вместо того, чтобы явно устанавливать приоритет «Высокий» или «Низкий», а относительный приоритет определяет браузер. Часто это «Высокий» или «Низкий», но не всегда. Например, критический CSS с fetchpriority="high" по-прежнему будет сохранять приоритет "VeryHigh"/"Highest", а использование fetchpriority="low" для них по-прежнему будет сохранять приоритет "High" — ни в том, ни в другом случае приоритет не установлен явно. на «Высокий» или «Низкий».

Случаи использования

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

Увеличьте приоритет изображения LCP.

Вы можете указать fetchpriority="high" , чтобы повысить приоритет LCP или других важных изображений.

<img src="lcp-image.jpg" fetchpriority="high">

Следующее сравнение показывает страницу Google Flights с фоновым изображением LCP, загруженным с приоритетом выборки и без него. При установке высокого приоритета время LCP улучшилось с 2,6 с до 1,9 с .

Эксперимент проводился с использованием работников Cloudflare, чтобы переписать страницу Google Flights для использования приоритета выборки.

Понизьте приоритет изображений, расположенных выше сгиба.

Вы можете использовать fetchpriority="low" , чтобы понизить приоритет изображений в верхней части экрана, которые изначально могут быть неважными, например в карусели изображений.

<ul class="carousel">
  <img src="img/carousel-1.jpg" fetchpriority="high">
  <img src="img/carousel-2.jpg" fetchpriority="low">
  <img src="img/carousel-3.jpg" fetchpriority="low">
  <img src="img/carousel-4.jpg" fetchpriority="low">
</ul>

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

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

Понизить приоритет предварительно загруженных ресурсов

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

<!-- Lower priority only for non-critical preloaded scripts -->
<link rel="preload" as="script" href="critical-script.js">
<link rel="preload" href="/js/script.js" as="script" fetchpriority="low">

<!-- Preload CSS without blocking other resources -->
<link rel="preload" as="style" href="theme.css" fetchpriority="low" onload="this.rel='stylesheet'">

Изменение приоритетов сценариев

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

<script src="async_but_important.js" async fetchpriority="high"></script>

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

<script src="blocking_but_unimportant.js" fetchpriority="low"></script>

Понизьте приоритет для выборки некритических данных.

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

// Important validation data (high by default)
let authenticate = await fetch('/user');

// Less important content data (suggested low)
let suggestedContent = await fetch('/content/suggested', {priority: 'low'});

Замечания по реализации Fetch Priority

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

  • Атрибут fetchpriority является подсказкой, а не директивой. Браузер постарается учесть предпочтения разработчика. Также возможно, что браузер применит свои настройки приоритета ресурсов, если сочтет это необходимым в случае конфликтов.
  • Приоритет выборки не следует путать с предварительной загрузкой. Они оба различны, потому что:

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

    Fetch Priority может дополнять предварительную загрузку, увеличивая степень детализации приоритезации. Если вы уже указали предварительную загрузку в качестве одного из первых элементов в <head> для образа LCP, то high приоритет выборки может не привести к значительному выигрышу. Однако если предварительная загрузка была после других ресурсов, то high приоритет выборки может улучшить LCP. Если критическое изображение является фоновым изображением CSS, вам следует предварительно загрузить его с помощью fetchpriority = "high" .

  • Заметный выигрыш от расстановки приоритетов будет более актуален в средах, где больше ресурсов борются за доступную пропускную способность сети. Это характерно для соединений HTTP/1.x, где параллельная загрузка невозможна, или для соединений HTTP/2 с низкой пропускной способностью. Расстановка приоритетов может устранить узкие места в этих условиях.

  • CDN не всегда реализуют приоритезацию HTTP/2 . Даже если браузер сообщает приоритет, предложенный с помощью Fetch Priority; CDN не может изменить приоритеты ресурсов в требуемом порядке. Это затрудняет тестирование приоритета выборки. Приоритеты применяются как внутри браузера, так и с помощью протоколов, поддерживающих определение приоритетов (HTTP/2 и HTTP/3). Его по-прежнему стоит использовать даже для внутренней расстановки приоритетов браузера независимо от поддержки CDN или источника, поскольку это часто меняется, когда браузер запрашивает ресурсы — например, ресурсы с низким приоритетом, такие как изображения, часто не запрашиваются во время обработки браузером. критические элементы <head> .

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

Использование предварительной загрузки после Chrome 95

Функция Fetch Priority была доступна для пробной версии в Chrome 73–76, но не была выпущена из-за проблем с приоритизацией предварительных загрузок, исправленных в Chrome 95. До Chrome 95 запросы, отправленные через <link rel=preload> , всегда запускаются раньше других запросов, видимых сканер предварительной загрузки, даже если другие запросы имеют более высокий приоритет.

Мы надеемся, что с исправлением в Chrome 95 и улучшением Fetch Priority разработчики начнут использовать предварительную загрузку по прямому назначению — для предварительной загрузки ресурсов, не обнаруженных парсером (шрифты, импорт, фоновые изображения LCP). Размещение подсказки о preload будет влиять на то, когда ресурс будет предварительно загружен. Некоторые ключевые моменты использования предварительной загрузки:

  • Включение предварительной загрузки в заголовки HTTP приведет к тому, что она опередит все остальное.
  • Как правило, предварительные загрузки загружаются в том порядке, в котором анализатор получает их для всего, что имеет приоритет выше «Среднего», поэтому будьте осторожны, если вы включаете предварительные загрузки в начало HTML.
  • Предварительная загрузка шрифта, вероятно, будет лучше всего работать в конце заголовка или начале тела.
  • Предварительную загрузку импорта (динамический import() или modulepreload ) следует выполнять после тега сценария, который требует импорта (чтобы фактический сценарий загружался/анализировался первым). По сути, если тег сценария загружает сценарий, который запускает загрузку зависимостей, убедитесь, что <link rel=preload> для зависимостей находится после тега родительского сценария, в противном случае зависимости могут загружаться раньше основного сценария. В правильном порядке основной скрипт можно анализировать/оценивать во время загрузки зависимостей.
  • Предварительные загрузки изображений имеют приоритет «Низкий» или «Средний» (без приоритета выборки) и должны быть упорядочены относительно асинхронных сценариев и других тегов с низким или самым низким приоритетом.

История

Впервые с приоритетом выборки экспериментировали в Chrome в качестве пробной версии источника в 2018 году, а затем снова в 2021 году с использованием атрибута importance . В то время это было известно как Priority Hints . С тех пор интерфейс изменился на fetchpriority для HTML и priority для Fetch API JavaScript в рамках процесса веб-стандартов. Чтобы избежать путаницы, мы теперь называем этот API приоритетом выборки.

Заключение

Разработчиков, вероятно, заинтересует Fetch Priority с исправлениями в поведении предварительной загрузки и недавним акцентом на Core Web Vitals и LCP. Теперь у них есть дополнительные ручки для достижения желаемой последовательности загрузки.