Codelab: предварительная загрузка критически важных ресурсов для повышения скорости загрузки

Хуссейн Джирдех
Houssein Djirdeh

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

Скриншот приложения

Мера

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

  • Для предварительного просмотра сайта нажмите «Просмотреть приложение» . Затем нажмите «Полный экран». полноэкранный .

Запустите аудит производительности Lighthouse ( Lighthouse > Параметры > Производительность ) на работающей версии вашего Glitch (см. также раздел Откройте для себя возможности повышения производительности с помощью Lighthouse ).

Lighthouse показывает следующий неудавшийся аудит для ресурса, извлеченного поздно:

Lighthouse: Аудит запросов на предварительную загрузку ключей
  • Нажмите `Control+Shift+J` (или `Command+Option+J` на Mac), чтобы открыть DevTools.
  • Откройте вкладку Сеть .
Сетевая панель с поздно обнаруженным ресурсом

Файл main.css не загружается элементом Link ( <link> ), размещённым в HTML-документе, а отдельный JavaScript-файл fetch-css.js , который прикрепляет элемент Link к DOM после события window.onLoad . Это означает, что файл загружается только после того, как браузер завершит парсинг и выполнение JS-файла. Аналогично, веб-шрифт ( K2D.woff2 ), указанный в main.css загружается только после завершения загрузки CSS-файла.

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

├─┬ / (initial HTML file)
  └── fetch-css.js
    └── main.css
      └── K2D.woff2

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

Предварительная загрузка критических ресурсов

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

Добавьте тег предварительной загрузки для этого приложения:

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
</head>

Атрибут as используется для определения типа извлекаемого ресурса, а as="style" — для предварительной загрузки файлов таблиц стилей.

Перезагрузите приложение и взгляните на панель «Сеть» в DevTools.

Сетевая панель с предустановленным ресурсом

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

При неправильном использовании предварительная загрузка может снизить производительность, выполняя ненужные запросы к неиспользуемым ресурсам. В этом приложении details.css — это ещё один CSS-файл, расположенный в корне проекта, но используемый для отдельного /details route . Чтобы показать пример неправильного использования предварительной загрузки, добавьте подсказку о предварительной загрузке и для этого ресурса.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

Перезагрузите приложение и взгляните на панель «Сеть» . Выполняется запрос на получение файла details.css , хотя он не используется веб-страницей.

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

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

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

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

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

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

Предварительная выборка будущих ресурсов

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

На этом сайте нажатие на изображение перенесет вас на отдельную details/ маршрут.

Подробный маршрут

Отдельный CSS-файл details.css содержит все стили, необходимые для этой простой страницы. Добавьте элемент link в index.html для предварительной загрузки этого ресурса.

<head>
  <!-- ... -->
  <link rel="prefetch" href="details.css">
</head>

Чтобы понять, как это инициирует запрос файла, откройте панель «Сеть» в DevTools и снимите флажок «Отключить кэш» .

Отключить кэш в Chrome DevTools

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

Сетевая панель с предварительно загруженным ресурсом

Открыв DevTools, нажмите на изображение на сайте, чтобы перейти на страницу details . Поскольку в details.html используется элемент link для получения details.css , запрос к ресурсу выполняется, как и ожидалось.

Страница сведений о сетевых запросах

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

Запрос сведений извлечен из дискового кэша

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

Предварительная загрузка и предварительная выборка с помощью Webpack

В статье «Сокращение объёма JavaScript-данных с помощью разделения кода» рассматривается использование динамического импорта для разделения пакета на несколько фрагментов. Это демонстрируется на примере простого приложения, которое динамически импортирует модуль из Lodash при отправке формы.

Приложение Magic Sorter, демонстрирующее разделение кода

Вы можете получить доступ к Glitch для этого приложения здесь .

Следующий блок кода, который находится в src/index.js, отвечает за динамический импорт метода при нажатии кнопки.

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

Разделение пакета ускоряет загрузку страницы за счёт уменьшения его начального размера. Webpack версии 4.6.0 поддерживает предварительную загрузку или предвыборку динамически импортируемых фрагментов. На примере этого приложения метод lodash может быть предварительно загружен во время простоя браузера; когда пользователь нажимает кнопку, загрузка ресурса происходит без задержки.

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

form.addEventListener("submit", e => {
  e.preventDefault()
  import(/* webpackPrefetch: true */ 'lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

После перезагрузки приложения Webpack внедряет тег предварительной выборки ресурса в заголовок документа. Это можно увидеть на панели «Элементы» в DevTools.

Панель элементов с тегом предварительной выборки

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

Сетевая панель с предварительно загруженным запросом

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

import(/* webpackPreload: true */ 'module')

Заключение

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

Подведем итог:

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

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

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