---
layout: post
title: Настройте предварительную загрузку критических ресурсов для повышения скорости загрузки
authors:
  - houssein
  - mihajlija
description: Как только вы открываете любую веб-страницу, браузер запрашивает HTML-документ с сервера, анализирует содержимое HTML-файла и отправляет отдельные запросы на любые другие внешние ссылки. Цепочка критических запросов представляет собой установленный браузером порядок выборки ресурсов.
date: 2018-11-05
updated: 2020-05-27
codelabs:
  - codelab-preload-critical-assets
  - codelab-preload-web-fonts
tags:
  - performance
feedback:
  - api
---

Когда вы открываете веб-страницу, браузер запрашивает HTML-документ с сервера, анализирует его содержимое и отправляет отдельные запросы на любые ресурсы, на которые ссылается страница. Как разработчик, вы уже знаете обо всех ресурсах, необходимых вашей странице, и о том, какие из них наиболее важны. Вы можете использовать эти знания, чтобы заблаговременно запросить критические ресурсы и ускорить процесс загрузки. В этой статье объясняется, как можно это сделать с помощью `<link rel="preload">`.

## Как работает предварительная загрузка

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

<figure>{% Img src="image/admin/Ad9PLq3DcQt9Ycp63z6O.png", alt="Скриншот панели Network (Сеть) в Chrome DevTools.", width="701", height="509" %} <figcaption>В этом примере шрифт Pacifico определяется в таблице стилей правилом <a href="/reduce-webfont-size/#defining-a-font-family-with-@font-face)"><code>@font-face</code></a>. Браузер загружает файл шрифта только после завершения загрузки и анализа таблицы стилей.</figcaption></figure>

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

<figure>{% Img src="image/admin/PgRbERrxLGfF439yBMeY.png", alt="Скриншот панели Network (Сеть) в Chrome DevTools после применения предварительной загрузки.", width="701", height="509" %} <figcaption>В этом примере предварительно загружается шрифт Pacifico, поэтому его загрузка происходит параллельно с таблицей стилей.</figcaption></figure>

Цепочка критических запросов представляет собой установленный браузером порядок выборки ресурсов. Lighthouse определяет ресурсы, которые находятся на третьем уровне этой цепочки, как поздно обнаруженные. Вы можете использовать аудит [**Preload key requests (Настройте предварительную загрузку ключевых запросов)**](https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preload/), чтобы определить, какие ресурсы необходимо загружать заранее.

{% Img src="image/admin/BPUTHBNZFbeXqb0dVx2f.png", alt="Аудит Preload key requests (Настройте предварительную загрузку ключевых запросов) в Lighthouse.", width="745", height="97" %}

Вы можете настроить предварительную загрузку ресурсов, добавив тег `<link>` с атрибутом `rel="preload"` в заголовок HTML-документа:

```html
<link rel="preload" as="script" href="critical.js">
```

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

{% Aside %} После внедрения предварительной загрузки на многих сайтах, включая [Shopify, Financial Times и Treebo, на 1 секунду были улучшены](https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf) такие ориентированные на пользователя метрики, как [TTI (Время до интерактивности)](/tti/) и [FCP (Первая отрисовка контента)](/fcp/). {% endAside %}

Ресурсные подсказки, например [`preconnect`](/preconnect-and-dns-prefetch) и [`prefetch`](/link-prefetch), выполняются по усмотрению браузера, тогда как `preload` является обязательной для браузера. Современные браузеры уже довольно хорошо определяют приоритеты ресурсов, поэтому необходимо использовать `preload` точечно и только для предварительной загрузки самых критических ресурсов.

Неиспользованные предварительные загрузки вызывают предупреждение на вкладке Console (Консоль) в Chrome DevTools примерно через 3 секунды после события `load`.

{% Img src="image/admin/z4FbCezjXHxaIhq188TU.png", alt="Предупреждение на вкладке Console в Chrome DevTools о неиспользуемых предварительно загруженных ресурсах.", width="800", height="228" %}

{% Aside %} [`preload` поддерживается](https://developer.mozilla.org/docs/Web/HTML/Preloading_content#Browser_compatibility) во всех современных браузерах. {% endAside %}

## Сценарии использования

{% Aside 'caution' %} На момент написания статьи в Chrome имелась неисправленная [ошибка](https://bugs.chromium.org/p/chromium/issues/detail?id=788757), связанная с тем, что предварительно загружаемые запросы извлекаются раньше, чем запросы ресурсов с более высоким приоритетом. Пока эта проблема не будет решена, учитывайте, что предварительно загружаемые ресурсы могут «обойти очередь» и запрашиваться раньше, чем следовало бы. {% endAside %}

### Предварительная загрузка ресурсов, определенных в CSS

Шрифты, определенные с помощью правил [`@font-face`](/reduce-webfont-size/#defining-a-font-family-with-@font-face) или фоновые изображения, определенные в файлах CSS, не обнаруживаются, пока браузер не загрузит и не проанализирует эти файлы CSS. Предварительная загрузка этих ресурсов гарантирует, что они будут получены до загрузки файлов CSS.

### Предварительная загрузка файлов CSS

Если вы используете [критический подход к обработке CSS-кода](/extract-critical-css), разделите CSS-код на две части. Критический CSS-код, необходимый для рендеринга контента в области просмотра, встраивается в `<head>` документа, а некритический CSS-код обычно загружается с помощью JavaScript с отложенной загрузкой. Ожидание выполнения JavaScript перед загрузкой некритического CSS-кода может вызвать задержки в отрисовке страницы при прокрутке, поэтому рекомендуется использовать `<link rel="preload">`, чтобы начать загрузку раньше.

### Предварительная загрузка файлов JavaScript

Поскольку браузеры не выполняют предварительно загруженные файлы, предварительная загрузка полезна для отделения выборки от [выполнения](https://developer.chrome.com/docs/lighthouse/performance/bootup-time/). Это может улучшить такие метрики, как TTI (Время до интерактивности). Предварительная загрузка сработает эффективнее, если вы [разделите](/reduce-javascript-payloads-with-code-splitting) пакеты JavaScript и предварительно загрузите только критические фрагменты.

## Как реализовать rel = preload

Самый простой способ реализовать `preload` — это добавить тег `<link>` к `<head>` документа:

```html
<head>
  <link rel="preload" as="script" href="critical.js">
</head>
```

Использование атрибута `as` помогает браузеру установить приоритет предварительно извлеченного ресурса в соответствии с его типом, установить правильные заголовки и определить, существует ли уже ресурс в кеше. Допустимые значения для этого атрибута: `script`, `style`, `font`, `image` и [другие](https://developer.mozilla.org/docs/Web/HTML/Element/link#Attributes).

{% Aside %} Ознакомьтесь с документом [Chrome Resource Priorities and Scheduling](https://docs.google.com/document/d/1bCDuq9H1ih9iNjgzyAL0gpwNFiEP4TZS-YLRp_RuMlc/edit) (Приоритетность и планирование загрузки ресурсов в Chrome), чтобы больше узнать о том, как браузер устанавливает приоритеты для различных типов ресурсов. {% endAside %}

{% Aside 'caution' %} Отсутствие атрибута `as` или наличие недопустимого значения эквивалентно [XHR-запросу](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest), когда браузер не знает, что он извлекает, поэтому не может определить правильный приоритет. Это также может привести к тому, что некоторые ресурсы, например сценарии, будут получены дважды. {% endAside %}

Некоторые типы ресурсов, например шрифты, загружаются в [анонимном режиме](https://www.w3.org/TR/css-fonts-3/#font-fetching-requirements) . Для них вы должны установить атрибут `crossorigin` с `preload`:

```html
<link rel="preload" href="ComicSans.woff2" as="font" type="font/woff2" crossorigin>
```

{% Aside 'caution' %} Предварительно загруженные шрифты без атрибута `crossorigin` будут извлечены дважды! {% endAside %}

Элементы `<link>` также принимают [атрибут `type`](https://developer.mozilla.org/docs/Web/HTML/Element/link#attr-type), который содержит [MIME-тип](https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/MIME_types) связанного ресурса. Браузеры используют значение `type`, чтобы обеспечить предварительную загрузку ресурсов только в том случае, если их тип файла поддерживается. Если браузер не поддерживает указанный тип ресурса, он проигнорирует `<link rel="preload">`.

{% Aside 'codelab' %} [Повысьте производительность страницы, предварительно загрузив веб-шрифты](/codelab-preload-web-fonts). {% endAside %}

Вы также можете предварительно загрузить любой тип ресурса через [HTTP-заголовок `Link`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Link) :

`Link: </css/style.css>; rel="preload"; as="style"`

Преимущество указания `preload` в HTTP-заголовке заключается в том, что браузеру не нужно анализировать документ, чтобы обнаружить preload. Это может дать небольшие улучшения в некоторых случаях.

### Предварительная загрузка модулей JavaScript с помощью webpack

Если вы используете сборщик модулей, который создает файлы сборки вашего приложения, вам необходимо проверить, поддерживает ли он внедрение тегов предварительной загрузки. В [webpack](https://webpack.js.org/) версии 4.6.0 или новее предварительная загрузка поддерживается за счет использования [волшебных комментариев](https://webpack.js.org/api/module-methods/#magic-comments) внутри `import()`:

```js
import(_/* webpackPreload: true */_ "CriticalChunk")
```

Если у вас старая версия webpack, используйте сторонний плагин, например [preload-webpack-plugin](https://github.com/GoogleChromeLabs/preload-webpack-plugin).

## Заключение

Чтобы повысить скорость загрузки страниц, предварительно загружайте важные ресурсы, которые браузер обнаруживает с опозданием. Предварительная загрузка всего будет контрпродуктивна, поэтому используйте `preload` точечно и [измеряйте воздействие в реальных условиях](/fast#measure-performance-in-the-field).
