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

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

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

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

Что такое сканер предварительной загрузки?

В каждом браузере есть основной анализатор HTML, который маркирует необработанную разметку и преобразует ее в объектную модель . Все это весело продолжается до тех пор, пока парсер не остановится, когда обнаружит блокирующий ресурс , например, таблицу стилей, загруженную с элементом <link> , или скрипт, загруженный с элементом <script> без атрибута async или defer .

Схема парсера HTML.
Рис. 1: Схема блокировки основного HTML-парсера браузера. В этом случае анализатор сталкивается с элементом <link> для внешнего файла CSS, который блокирует браузер от анализа остальной части документа — или даже отрисовки какой-либо его части — до тех пор, пока CSS не будет загружен и проанализирован.

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

Домашняя страница web.dev в нестилизованном состоянии (слева) и стилизованном состоянии (справа).
Рис. 2: Моделируемый пример FOUC. Слева — главная страница web.dev без стилей. Справа — та же страница с примененными стилями. Нестилизованное состояние может возникнуть мгновенно, если браузер не блокирует рендеринг во время загрузки и обработки таблицы стилей.

Браузер также блокирует синтаксический анализ и рендеринг страницы, когда он встречает элементы <script> без атрибута defer или async .

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

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

Схема основного анализатора HTML (слева) и сканера предварительной загрузки (справа), который является вторичным анализатором HTML.
Рис. 3. Диаграмма, показывающая, как сканер предварительной загрузки работает параллельно с основным парсером HTML для спекулятивной загрузки ресурсов. Здесь основной анализатор HTML блокируется, поскольку он загружает и обрабатывает CSS, прежде чем он сможет начать обработку разметки изображения в элементе <body> , но сканер предварительной загрузки может просмотреть необработанную разметку, чтобы найти этот ресурс изображения и начать его загрузку до того, как основной парсер HTML разблокирован.

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

Как определить, что сканер предварительной загрузки работает

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

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

Сетевая каскадная диаграмма WebPageTest иллюстрирует искусственную задержку в 2 секунды, введенную в таблицу стилей.
Рис. 4. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Несмотря на то, что таблица стилей искусственно задерживается через прокси-сервер на две секунды, прежде чем она начнет загружаться, изображение, расположенное позже в полезных данных разметки, обнаруживается сканером предварительной загрузки.

Как вы можете видеть на водопаде, сканер предварительной загрузки обнаруживает элемент <img> даже тогда, когда рендеринг и синтаксический анализ документа заблокированы . Без этой оптимизации браузер не сможет оперативно извлекать данные в период блокировки, и больше запросов на ресурсы будут последовательными, а не одновременными.

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

Внедренные async скрипты

Допустим, у вас есть HTML в <head> , который включает в себя встроенный JavaScript, например:

<script>
 
const scriptEl = document.createElement('script');
  scriptEl
.src = '/yall.min.js';

  document
.head.appendChild(scriptEl);
</script>

Внедренные скрипты по умолчанию являются async , поэтому при внедрении этого скрипта он будет вести себя так, как если бы к нему был применен атрибут async . Это означает, что он запустится как можно скорее и не заблокирует рендеринг. Звучит оптимально, не так ли? Тем не менее, если вы предполагаете, что этот встроенный <script> идет после элемента <link> , который загружает внешний файл CSS, вы получите неоптимальный результат:

На этой диаграмме WebPageTest показано, что сканирование предварительной загрузки завершилось неудачно при внедрении сценария.
Рис. 5. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Страница содержит одну таблицу стилей и внедренный async скрипт. Сканер предварительной загрузки не может обнаружить сценарий на этапе блокировки рендеринга, поскольку он внедряется в клиент.

Давайте разберем, что здесь произошло:

  1. В 0 секунд запрашивается основной документ.
  2. Через 1,4 секунды приходит первый байт навигационного запроса.
  3. Через 2,0 секунды запрашиваются CSS и изображение.
  4. Поскольку синтаксический анализатор блокирует загрузку таблицы стилей, а встроенный код JavaScript, который внедряет async сценарий, появляется после этой таблицы стилей через 2,6 секунды, функциональность, предоставляемая сценарием, недоступна так быстро, как могла бы.

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

Итак, что произойдет, если вы используете обычный тег <script> с атрибутом async вместо внедрения сценария в DOM?

<script src="/yall.min.js" async></script>

Вот результат:

Сетевой водопад WebPageTest, показывающий, как асинхронный сценарий, загруженный с помощью элемента сценария HTML, по-прежнему доступен для обнаружения сканером предварительной загрузки браузера, даже несмотря на то, что основной анализатор HTML браузера блокируется во время загрузки и обработки таблицы стилей.
Рис. 6. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Страница содержит одну таблицу стилей и один async элемент <script> . Сканер предварительной загрузки обнаруживает скрипт на этапе блокировки рендеринга и загружает его одновременно с CSS.

Может возникнуть соблазн предположить, что эти проблемы можно решить, используя rel=preload . Это, безусловно, сработает, но может повлечь за собой некоторые побочные эффекты. В конце концов, зачем использовать rel=preload для решения проблемы, которой можно избежать, не внедряя элемент <script> в DOM?

Водопад WebPageTest, показывающий, как подсказка ресурса rel=preload используется для содействия обнаружению внедренного асинхронного сценария, хотя и таким образом, который может иметь непредвиденные побочные эффекты.
Рис. 7. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Страница содержит одну таблицу стилей и внедренный async сценарий, но async сценарий предварительно загружен, чтобы обеспечить его более быстрое обнаружение.

Предварительная загрузка «исправляет» проблему здесь, но создает новую проблему: async скрипт в первых двух демонстрациях, несмотря на то, что он загружается в <head> , загружается с «низким» приоритетом, тогда как таблица стилей загружается с «самым высоким» приоритетом. приоритет. В последней демонстрации, где предварительно загружен async сценарий, таблица стилей по-прежнему загружается с «самым высоким» приоритетом, но приоритет сценария повышен до «Высокого».

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

Ответ здесь прост: если во время запуска необходим скрипт, не побеждайте сканер предварительной загрузки, внедряя его в DOM. При необходимости поэкспериментируйте с размещением элемента <script> , а также с такими атрибутами, как defer и async .

Ленивая загрузка с помощью JavaScript

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

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

<img data-src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

Использование префикса data- является обычным явлением в ленивых загрузчиках на основе JavaScript. Когда изображение прокручивается в область просмотра, ленивый загрузчик удаляет префикс data- , что означает, что в предыдущем примере data-src становится src . Это обновление предлагает браузеру получить ресурс.

Этот шаблон не представляет проблем, пока он не будет применен к изображениям, которые находятся в области просмотра во время запуска. Поскольку сканер предварительной загрузки не считывает атрибут data-src так же, как атрибут src (или srcset ), ссылка на изображение не обнаруживается раньше. Хуже того, загрузка изображения задерживается до тех пор, пока ленивый загрузчик JavaScript не загрузит, не скомпилирует и не выполнит.

Сетевая каскадная диаграмма WebPageTest, показывающая, как лениво загружаемое изображение, которое находится в области просмотра во время запуска, обязательно задерживается, поскольку сканер предварительной загрузки браузера не может найти ресурс изображения и загружается только тогда, когда загружается JavaScript, необходимый для работы отложенной загрузки. Изображение обнаружено гораздо позже, чем должно быть.
Рис. 8. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Ресурс изображения загружается излишне лениво, хотя он виден в области просмотра во время запуска. Это отключает сканер предварительной загрузки и вызывает ненужную задержку.

В зависимости от размера изображения, который может зависеть от размера области просмотра, он может быть элементом-кандидатом на звание Largest Contentful Paint (LCP) . Когда сканер предварительной загрузки не может спекулятивно получить ресурс изображения заранее (возможно, в тот момент, когда таблица стилей страницы блокирует рендеринг), страдает LCP.

Решение — изменить разметку изображения:

<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

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

Сетевая каскадная диаграмма WebPageTest, изображающая сценарий загрузки изображения в области просмотра во время запуска. Изображение не загружается лениво, что означает, что оно не зависит от загрузки сценария, а это означает, что сканер предварительной загрузки может обнаружить его раньше.
Рис. 9. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Сканер предварительной загрузки обнаруживает ресурс изображения до начала загрузки CSS и JavaScript, что дает браузеру преимущество при его загрузке.

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

Фоновые изображения CSS

Помните, что сканер предварительной загрузки браузера сканирует разметку . Он не сканирует другие типы ресурсов, такие как CSS, которые могут включать выборку изображений, на которые ссылается свойство background-image .

Как и HTML, браузеры преобразуют CSS в собственную объектную модель, известную как CSSOM . Если внешние ресурсы обнаруживаются при построении CSSOM, эти ресурсы запрашиваются во время обнаружения, а не сканером предварительной загрузки.

Допустим, кандидат LCP вашей страницы — это элемент со свойством CSS background-image . Вот что происходит при загрузке ресурсов:

Сетевая каскадная диаграмма WebPageTest, изображающая страницу с кандидатом LCP, загруженным из CSS с использованием свойства фонового изображения. Поскольку изображение-кандидат LCP относится к типу ресурса, который сканер предварительной загрузки браузера не может проверить, загрузка ресурса задерживается до тех пор, пока CSS не будет загружен и обработан, что задерживает время отрисовки кандидата LCP.
Рис. 10. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Кандидатом LCP страницы является элемент со свойством CSS background-image (строка 3). Запрашиваемое изображение не начнет получаться до тех пор, пока синтаксический анализатор CSS не найдет его.

В этом случае сканер предзагрузки не столько побежден, сколько не задействован. Тем не менее, если кандидат LCP на странице взят из CSS background-image , вам потребуется предварительно загрузить это изображение:

<!-- Make sure this is in the <head> below any
     stylesheets, so as not to block them from loading -->

<link rel="preload" as="image" href="lcp-image.jpg">

Подсказка rel=preload невелика, но она помогает браузеру обнаружить изображение раньше, чем в противном случае:

Сетевая каскадная диаграмма WebPageTest, показывающая фоновое изображение CSS (которое является кандидатом на LCP), загружающееся гораздо быстрее из-за использования подсказки rel=preload. Время LCP увеличивается примерно на 250 миллисекунд.
Рис. 11. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Кандидатом LCP страницы является элемент со свойством CSS background-image (строка 3). Подсказка rel=preload помогает браузеру обнаружить изображение примерно на 250 миллисекунд раньше, чем без подсказки.

Благодаря подсказке rel=preload кандидат LCP обнаруживается раньше, что сокращает время LCP. Хотя эта подсказка помогает решить эту проблему, лучшим вариантом может быть оценка того, нужно ли загружать кандидата LCP вашего изображения из CSS. С помощью тега <img> вы получите больше контроля над загрузкой изображения, подходящего для области просмотра, и при этом позволите сканеру предварительной загрузки обнаружить его.

Встраивание слишком большого количества ресурсов

Встраивание — это практика размещения ресурса внутри HTML. Вы можете встроить таблицы стилей в элементы <style> , скрипты в элементы <script> и практически любой другой ресурс, используя кодировку base64 .

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

  • Если вы не кэшируете свой HTML (а вы просто не можете этого сделать, если ответ HTML является динамическим), встроенные ресурсы никогда не кэшируются. Это влияет на производительность, поскольку встроенные ресурсы нельзя использовать повторно.
  • Даже если вы можете кэшировать HTML, встроенные ресурсы не распределяются между документами. Это снижает эффективность кэширования по сравнению с внешними файлами, которые можно кэшировать и повторно использовать по всему источнику.
  • Если вы встраиваете слишком много данных, вы задерживаете поиск ресурсов сканером предварительной загрузки в документе, поскольку загрузка этого дополнительного встроенного контента занимает больше времени.

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

Сетевая каскадная диаграмма страницы WebPageTest с внешним CSS-файлом, в котором указаны четыре шрифта. Образ-кандидат LCP своевременно обнаруживается сканером предварительной загрузки.
Рис. 12. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Кандидатом LCP страницы является изображение, загружаемое из элемента <img> , но оно обнаруживается сканером предварительной загрузки, поскольку CSS и шрифты, необходимые для страницы, загружаются в отдельные ресурсы, что не мешает сканеру предварительной загрузки выполнять свою работу.

Что же произойдет, если CSS и все шрифты будут встроены в ресурсы base64?

Сетевая каскадная диаграмма страницы WebPageTest с внешним CSS-файлом, в котором указаны четыре шрифта. Сканер предварительной загрузки значительно задерживается при обнаружении образа LCP.
Рис. 13. Водопадная диаграмма сети WebPageTest для веб-страницы , запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Кандидатом LCP страницы является изображение, загруженное из элемента <img> , но встраивание CSS и четырех ресурсов шрифтов в ` ` задерживает обнаружение изображения сканером предварительной загрузки до тех пор, пока эти ресурсы не будут полностью загружены.

Влияние встраивания приводит к негативным последствиям для LCP в этом примере — и для производительности в целом. Версия страницы, которая ничего не встраивает, рисует изображение LCP примерно за 3,5 секунды. Страница, на которой все встраивается, не рисует изображение LCP чуть более 7 секунд.

Здесь задействовано нечто большее, чем просто сканер предварительной загрузки. Встраивание шрифтов — не лучшая стратегия, поскольку base64 — неэффективный формат для двоичных ресурсов. Еще одним важным фактором является то, что внешние ресурсы шрифтов не загружаются, если они не определены CSSOM как необходимые. Когда эти шрифты встроены в кодировку Base64, они загружаются независимо от того, нужны они для текущей страницы или нет.

Может ли предварительная загрузка улучшить ситуацию? Конечно. Вы можете предварительно загрузить изображение LCP и сократить время LCP, но раздувание потенциально некэшируемого HTML-кода встроенными ресурсами имеет и другие негативные последствия для производительности. Этот шаблон также влияет на First Contentful Paint (FCP) . В версии страницы, где ничего не встроено, FCP составляет примерно 2,7 секунды. В версии, где все встроено, FCP составляет примерно 5,8 секунды.

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

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

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

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

Сетевой водопад WebPageTest, показывающий базовую страницу с изображениями и текстом, полностью отображаемыми на клиенте с помощью JavaScript. Поскольку разметка содержится в JavaScript, сканер предварительной загрузки не может обнаружить ни один из ресурсов. Все ресурсы дополнительно задерживаются из-за дополнительной сети и времени обработки, которые требуются платформам JavaScript.
Рис. 14. Водопадная диаграмма сети WebPageTest для веб-страницы, отображаемой клиентом, запускаемой в Chrome на мобильном устройстве через моделируемое соединение 3G. Поскольку содержимое содержится в JavaScript и для его рендеринга используется платформа, ресурс изображения в разметке, отображаемой клиентом, скрыт от сканера предварительной загрузки. Эквивалентный опыт визуализации на сервере показан на рис. 9 .

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

Это немного отклоняется от темы данной статьи, но эффект от рендеринга разметки на клиенте выходит далеко за рамки победы над сканером предварительной загрузки. Во-первых, внедрение JavaScript для обеспечения работы, которая не требует его, приводит к ненужному времени обработки, которое может повлиять на взаимодействие со следующей отрисовкой (INP) . Отрисовка чрезвычайно больших объемов разметки на клиенте с большей вероятностью приведет к созданию длительных задач по сравнению с тем же объемом разметки, отправляемым сервером. Причина этого (помимо дополнительной обработки, которую включает в себя JavaScript) заключается в том, что браузеры передают разметку с сервера и фрагментируют рендеринг таким образом, что это приводит к ограничению длительных задач. С другой стороны, разметка, отображаемая клиентом, обрабатывается как единая монолитная задача, что может повлиять на INP страницы.

Решение этой ситуации зависит от ответа на следующий вопрос: есть ли причина, по которой разметка вашей страницы не может быть предоставлена ​​сервером, а не отображена на клиенте? Если ответ на этот вопрос «нет», следует рассмотреть возможность рендеринга на стороне сервера (SSR) или статически сгенерированной разметки, поскольку это поможет сканеру предварительной загрузки обнаружить и своевременно получить важные ресурсы заранее.

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

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

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

Подводя итог, вот следующие вещи, которые вы захотите вынести из этого поста:

  • Сканер предварительной загрузки браузера — это вторичный анализатор HTML, который сканирует перед основным, если он заблокирован, для своевременного обнаружения ресурсов, которые он может получить раньше.
  • Ресурсы, которых нет в разметке, предоставленной сервером в первоначальном запросе навигации, не могут быть обнаружены сканером предварительной загрузки. Способы обхода сканера предварительной загрузки могут включать (но не ограничиваться):
    • Внедрение ресурсов в DOM с помощью JavaScript, будь то сценарии, изображения, таблицы стилей или что-то еще, что было бы лучше использовать в исходной полезной нагрузке разметки с сервера.
    • Ленивая загрузка изображений или iframe над сгибом с помощью решения JavaScript.
    • Отрисовка разметки на клиенте, которая может содержать ссылки на подресурсы документа, с помощью JavaScript.
  • Сканер предварительной загрузки сканирует только HTML. Он не проверяет содержимое других ресурсов, особенно CSS, которые могут включать ссылки на важные ресурсы, включая кандидатов на LCP.

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

Ресурсы

Героическое изображение из Unsplash , автор Мохаммад Рахмани .