Предзагрузчик контента - rel="preload"

Этот перевод не завершён. Пожалуйста, помогите перевести эту статью с английского

Значение preload атрибута rel в элементе <link> позволяет вам запросить данные через <head> вашего HTML, указав необходимые вашей странице ресурсы ещё в начале её жизненного цикла, - до того, как сработает основной механизм отрисовки браузера. Это гарантирует, что предзагрузчик нужных ресурсов с меньшей вероятностью заблокирует отрисовку страницы, тем самым улучшая её производительность.

В этой статье приведено основное руководство про работе с <link rel="preload">.

Основы

Чаще всего вы используете простой <link> элемент, когда загружаете CSS файлы со стилем вашей страницы:

<link rel="stylesheet" href="styles/main.css">

Однако, здесь мы будем использовать значение preload для атрибута rel, которое превратит тег <link> в предзагрузчик для любого ресурса, который мы пожелаем. Для этого необходимо будет указать:

  • Адрес пути к ресурсу в атрибуте href;
  • Тип ресурса в атрибуте as.

Простой пример может выглядеть так: (смотрите наш JS и CSS пример из источника, и живой пример):

<head>
  <meta charset="utf-8">
  <title>Пример пред-загрузки JS и CSS</title>

  <link rel="preload" href="style.css" as="style">
  <link rel="preload" href="main.js" as="script">

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <h1>прыгающие шарики</h1>
  <canvas></canvas>

  <script src="main.js"></script>
</body>

Мы сделали предзагрузку наших файлов CSS и JavaScript, чтобы они стали доступны для рендеринга страницы сразу же, как это потребуется. Этот пример отчасти банален, поскольку браузер, вероятнее всего, обнаружит элементы <link rel="stylesheet"> и <script> в одном чанке (блоке) с основным HTML, но преимущества более явно проявятся, если далее по странице будут обнаружены более объёмные ресурсы. Это могут быть:

  • Ресурсы, на которые ссылаются стили из CSS (шрифты, изображения);
  • Ресурсы, затребованные из JavaScript (например JSON, динамически подгружаемые скрипты, воркеры);
  • Огромных размеров изображения, видео.

preload имеет и другие преимущества. Использование атрибута as для указания типа содержимого пред-загрузки позволит браузеру:

  • Точнее расставить приоритеты при загрузке ресурсов.
  • Сохранить в кэше затребованный ресурс для его повторного использования в случае необходимости.
  • Применять корректную политику безопасности содержимого (content security policy) для ресурсов.
  • Правильно устанавливать заголовки Accept для выбранного запроса.

Какие типы контента могут быть предзагружены?

Разного типа контент можно предзагрузить. Вот основные атрибуты значения as:

  • audio: Аудио файлы.
  • document: HTML документ для <frame> или <iframe>.
  • embed: Ресурс, встроенный в <embed> элемент.
  • fetch: Ресурс с доступом к запросу выборки или XHR, подобие файлу ArrayBuffer или JSON.
  • font: Шрифты.
  • image: Картинки.
  • object: Ресурс встроенный в <object> элемент.
  • script: JavaScript.
  • style: CSS таблица стилей.
  • track: WebVTT.
  • worker: A JavaScript веб-worker и общий worker.
  • video: Видео.

Заметка: Вы можете прочитать немного больше об этих значениях и веб-функциях, которыми они будут пользоваться, в спецификации Предзагрузка — расширения элементов ссылок. Также обратите внимание, что полный список значений атрибут as может принимать в зависимости от определений в спецификации Fetch — запрос направления.

Включение MIME-типов

Элементы <link> могут принимать атрибут type, содержащий MIME-тип ресурса целевого элемента. Это особенно полезно при пред-загрузке ресурсов. Браузер использует значение атрибута type и начнёт его загрузку, если поддержка ресурса определена, иначе проигнорирует его.

См. полный исходный код, (а также пример живой версии видео).

<head>
  <meta charset="utf-8">
  <title>Пример пред-загрузки видео</title>

  <link rel="preload" href="sintel-short.mp4" as="video" type="video/mp4">
</head>
<body>
  <video controls>
    <source src="sintel-short.mp4" type="video/mp4">
    <source src="sintel-short.webm" type="video/webm">
    <p> Ваш браузер не поддерживает видео в формате HTML5. 
        Взамен - <a href="sintel-short.mp4"> ссылка на видео </a>.</p>
  </video>
</body>

В этом случае браузеры, поддерживающие MP4, будут пред-загружать и использовать MP4, что, как мы надеемся, сделает видеоплеер плавнее/отзывчивее для пользователей. Браузеры, не поддерживающие MP4, могут загружать версию WebM, при этом не получая преимуществ пред-загрузки. Это показывает, как пред-загрузка контента может сочетаться с философией прогрессивного улучшения.

Выборки из разных источников

Если настройки CORS ваших сайтов правильные, вы можете успешно пред-загрузить ресурсы разных источников, установив атрибут crossorigin в элементе <link>.

Один из интересных случаев, когда это применимо, даже если выборка не из разных источников, - это файлы шрифтов. По разным причинам они должны быть получены с использованием анонимного режима CORS (см. Требования к выборке шрифтов, если вас заинтересуют все подробности).

Используем этот случай в качестве примера, во-первых, загрузка шрифтов - действительно хороший вариант использования пред-загрузки, а во-вторых, - это проще, чем настраивать пример запроса с перекрёстным источником. Полный пример исходного кода есть на GitHub (также смотрите его вживую):

<head>
  <meta charset="utf-8">
  <title>Примеры веб-шрифтов</title>

  <link rel="preload" href="fonts/cicle_fina-webfont.eot" as="font" type="application/vnd.ms-fontobject" crossorigin="anonymous">
  <link rel="preload" href="fonts/cicle_fina-webfont.woff2" as="font" type="font/woff2" crossorigin="anonymous">
  <link rel="preload" href="fonts/cicle_fina-webfont.woff" as="font" type="font/woff" crossorigin="anonymous">
  <link rel="preload" href="fonts/cicle_fina-webfont.ttf" as="font" type="font/ttf" crossorigin="anonymous">
  <link rel="preload" href="fonts/cicle_fina-webfont.svg" as="font" type="image/svg+xml" crossorigin="anonymous">

  <link rel="preload" href="fonts/zantroke-webfont.eot" as="font" type="application/vnd.ms-fontobject" crossorigin="anonymous">
  <link rel="preload" href="fonts/zantroke-webfont.woff2" as="font" type="font/woff2" crossorigin="anonymous">
  <link rel="preload" href="fonts/zantroke-webfont.woff" as="font" type="font/woff" crossorigin="anonymous">
  <link rel="preload" href="fonts/zantroke-webfont.ttf" as="font" type="font/ttf" crossorigin="anonymous">
  <link rel="preload" href="fonts/zantroke-webfont.svg" as="font" type="image/svg+xml" crossorigin="anonymous">

  <link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
  ...
</body>

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

Including media

One nice feature of <link> elements is their ability to accept media attributes. These can accept media types or full-blown media queries, allowing you to do responsive preloading!

Давайте посмотрим на очень простой пример (см. его на GitHub - исходный код и живой пример):

<head>
  <meta charset="utf-8">
  <title>Пример адаптивной предзагрузки</title>

  <link rel="preload" href="bg-image-narrow.png" as="image" media="(max-width: 600px)">
  <link rel="preload" href="bg-image-wide.png" as="image" media="(min-width: 601px)">

  <link rel="stylesheet" href="main.css">
</head>
<body>
  <header>
    <h1>Мой сайт</h1>
  </header>

  <script>
    var mediaQueryList = window.matchMedia("(max-width: 600px)");
    var header = document.querySelector('header');

    if(mediaQueryList.matches) {
      header.style.backgroundImage = 'url(bg-image-narrow.png)';
    } else {
      header.style.backgroundImage = 'url(bg-image-wide.png)';
    }
  </script>
</body>

Вы видите, что мы включаем media-атрибуты в наши элементы <link> так, чтобы узкое изображение пред-загружалось на устройство пользователя с узким экраном, а более широкое - на устройство с более широким экраном. Чтобы изображение к заголовку было в зависимости от результата - мы используем Window.matchMedia / MediaQueryList (подробности см. в разделе Тест медиа-запросов).

Это увеличивает вероятность того, что шрифт будет доступен к моменту завершения рендеринга страницы, что сокращает количество проблем с FOUT (вспышка нестилизованного текста).

Обратите внимание, что это не должно ограничиваться изображениями или даже файлами одного типа - думайте масштабно! Возможно, вы могли бы предварительно загрузить, а затем отобразить простую диаграмму SVG, если пользователь находится на узком экране, где пропускная способность и ЦП потенциально более ограничены, или предзагрузить сложный фрагмент JavaScript, а затем использовать его для рендеринга интерактивной 3D-модели, если ресурсы пользователя более многочисленны.

Скрипты и предзагрузки

Ещё одна полезная вещь в этих предзагрузках, это то, что вы можете выполнять их полностью со скриптами, если необходимо. Например, мы сейчас создаём  экземпляр HTMLLinkElement, затем включим её в DOM:

var preloadLink = document.createElement("link");
preloadLink.href = "myscript.js";
preloadLink.rel = "preload";
preloadLink.as = "script";
document.head.appendChild(preloadLink);

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

Чтобы выполнить его, вы можете использовать следующую конструкцию:

var preloadedScript = document.createElement("script");
preloadedScript.src = "myscript.js";
document.body.appendChild(preloadedScript);

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

Другие механизмы предзагрузки ресурсов

Существуют и другие функции предварительной загрузки, но ни одна из них не подходит так, как <link rel="preload">:

  • <link rel="prefetch"> давно поддерживается в браузерах, но предназначен для предварительной загрузки ресурсов, которые будут использоваться при следующей навигации/загрузке страницы (например, когда вы переходите на следующую страницу). Это нормально, но бесполезно для текущей страницы! Кроме того, браузеры будут отдавать ресурсам предварительной загрузки более низкий приоритет, чем ресурсам предзагрузки - текущая страница важнее следующей. См. Предвыборку ссылок FAQ для подробностей.
  • <link rel = "subresource"> некоторое время назад поддерживался в Chrome и предназначался для решения проблемы предзагрузки ресурсов для текущей навигации/загрузки страницы, но у него была проблема - не было возможности определить приоритет для получения элементов. (as тогда не существовало), поэтому все они в конечном итоге были извлечены с довольно низким приоритетом, что не помогло ситуации.
  • Существует ряд загрузчиков ресурсов на основе сценариев, но они не имеют никакой власти над очередью приоритетов выборки браузера и подвержены тем же проблемам с производительностью.

Характеристики

Specification Status Comment
Preload
Определение 'preload' в этой спецификации.
Кандидат в рекомендации Further details of preload.
HTML Living Standard
Определение 'rel=preload' в этой спецификации.
Живой стандарт Definition of rel=preload.

Совместимость с браузером

Update compatibility data on GitHub
КомпьютерыМобильные
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung Internet
preload
Экспериментальная
Chrome Полная поддержка 50Edge Полная поддержка ≤79Firefox Нет поддержки 56 — 57
Замечания
Нет поддержки 56 — 57
Замечания
Замечания Disabled due to various web compatibility issues (e.g. bug 1405761).
IE ? Opera Полная поддержка 37Safari ? WebView Android Полная поддержка 50Chrome Android Полная поддержка 50Firefox Android Нет поддержки 56 — 57
Замечания
Нет поддержки 56 — 57
Замечания
Замечания Disabled due to various web compatibility issues (e.g. bug 1405761).
Opera Android ? Safari iOS ? Samsung Internet Android Полная поддержка 5.0

Легенда

Полная поддержка  
Полная поддержка
Нет поддержки  
Нет поддержки
Совместимость неизвестна  
Совместимость неизвестна
Экспериментальная. Ожидаемое поведение может измениться в будущем.
Экспериментальная. Ожидаемое поведение может измениться в будущем.
Смотрите замечания реализации.
Смотрите замечания реализации.

Смотрите также