Есть много способов повышения веб-производительности. Один из них — предзагрузка контента, который понадобится позже. Префетчинг CSS, предварительный рендеринг полной страницы или резолвинг доменного имени. Делаем всё заранее, а потом мгновенно отображаем результат! Звучит круто.
Ещё круче, что это очень просто реализовано. Пять тегов <link rel> дают браузеру команду на предварительные действия:
Вкратце расскажем, что они делают и когда их использовать.
Перейти к: preload · prefetch · preconnect · dns-prefetch · prerender
Браузер ничего не делает с ресурсом после загрузки. Скрипты не выполняются, таблицы стилей не применяются. Ресурс просто кэшируется и немедленно предоставляется по запросу.
Важно указать атрибут
Используйте предзагрузку, когда ресурс понадобится в самое ближайшее время. Например:
Не злоупотребляйте предзагрузкой. Если загружать всё подряд, сайт не ускорится волшебным образом, скорее наоборот, это помешает браузеру грамотно планировать работу.
Не путайте с префетчингом. Не используйте
Это обязательный тег для исполнения браузером (если он его поддерживает), в отличие от всех других тегов <link>, связанных с предварительной загрузкой. Браузер обязан загрузить ресурс, указанный в
Приоритеты. Разным ресурсам (стили, скрипты, шрифты и т. д.), браузеры обычно назначают разные приоритеты, чтобы в первую очередь загружать самые важные ресурсы. В данном случае браузер определяет приоритет по атрибуту
Здесь тоже браузер ничего не делает с ресурсом после загрузки. Скрипты не выполняются, таблицы стилей не применяются. Ресурс просто кэшируется и немедленно предоставляется по запросу.
Важно указать атрибут
Для загрузки ресурсов с других страниц, если нужен ресурс с другой страницы, и вы хотите предварительно загрузить его, чтобы потом ускорить рендеринг этой страницы. Например:
Вероятно, этот тег можно безопасно использовать в любом объёме. Браузеры обычно планируют prefetch с наименьшим приоритетом, так что он никому не мешает. Только имейте в виду, что расходуется трафик пользователя, который может стоить денег.
Не для срочных запросов. Не используйте
Необязательный тег. Браузер не обязан следовать этой инструкции, он может проигнорировать её, например, на медленном соединении.
Приоритет в Chrome. В Chrome
Браузер должен установить соединение, если извлекает какие-то ресурсы с нового стороннего домена. Например, если загружает шрифты Google Fonts, React из CDN или запрашивает ответ JSON с сервера API.
Установка нового соединения обычно занимает несколько сотен миллисекунд. Она производится один раз, но всё равно отнимает время. Если вы заранее установили соединение, то сэкономите время и быстрее загрузите ресурсы с этого домена.
Используйте для доменов, которые скоро понадобятся для загрузки оттуда важного стиля, скрипта или изображения, но вы пока не знаете URL ресурса. Например:
Используйте этот тег, чтобы немного ускорить какой-то сторонний скрипт или стиль за счёт предварительной установки соединения.
Не злоупотребляйте. Установка и поддержание соединения — дорогостоящая операция как для клиента, так и для сервера. Используйте этот тег максимум для 4-6 доменов.
Необязательный тег. Браузер не обязан следовать этой инструкции и может проигнорировать её, например, если уже установлено много соединений или в каком-то другом случае.
Что включает в себя процесс подключения. Для подключения к каждому сайту браузер должен выполнить следующие действия:
Примечание: HTTP/3 улучшит и ускорит механизм рукопожатия, но он ещё далеко.
Браузер должен определить IP-адрес домена, если будет извлекать какие-то ресурсы с нового стороннего домена. Например, загружать шрифты Google Fonts, React из CDN или запрашивать ответ JSON с сервера API.
Для каждого нового домена разрешение записи DNS обычно занимает около 20−120 мс. Это влияет только на загрузку первого ресурса с данного домена, но всё равно представляет задержку. Если осуществить разрешение DNS заранее, то мы сэкономим время и загрузим ресурс быстрее.
Используйте для доменов, которые скоро понадобятся для загрузки оттуда ресурсов, о которых браузер не знает заранее. Например:
Используйте этот тег, чтобы немного ускорить какой-то сторонний скрипт или стиль за счёт предварительной установки соединения.
Необязательный тег. Браузер не обязан следовать этой инструкции, поэтому может не выполнять резолвинг DNS, например, если на странице много таких тегов или в каком-то другом случае.
Что такое DNS. Каждому серверу в интернете соответствует уникальный IP-адрес, который выглядит как
Чтобы определить IP-адрес, браузер должен выполнить запрос к DNS-серверу. Он занимает 20−120 мс при подключении к новому стороннему домену.
DNS кэшируется, хотя и не очень надёжно. Некоторые ОС и браузеры кэшируют DNS-запросы: это сэкономит время при повторных запросах, но на кэширование нельзя полагаться. В Linux оно обычно вообще не работает. У Chrome есть кэш DNS, но он живёт только минуту. Windows кэширует DNS-ответы в течение пяти дней.
Несмотря на исключительную эффективность этого тега (или из-за неё), в 2019 году
Когда вы действительно уверены, что пользователь перейдёт на определённую страницу. Если у вас «туннель», по которому 70% посетителей страницы A переходят на страницу Б, то
Не злоупотребляйте. Предварительный рендеринг чрезвычайно дорого обходится с точки зрения трафика и памяти. Не используйте
Необязательный тег. Браузер не обязан следовать этой инструкции и может проигнорировать её, например, на медленном соединении или при недостаточном объёме свободной памяти.
Ради экономии памяти Chrome не выполняет полный рендеринг, а только предзагрузку NoState. Это означает, что Chrome загружает страницу и все её ресурсы, но не делает рендеринг и не выполняет JavaScript.
Firefox и Safari вообще не поддерживают этот тег. Это не нарушает спецификацию, так как браузеры не обязаны выполнять данную инструкцию; но всё равно печально. Баг реализации в Firefox был открыт в течение семи лет. Есть сообщения, что Safari тоже не поддерживает этот тег.
Используйте:
Ещё круче, что это очень просто реализовано. Пять тегов <link rel> дают браузеру команду на предварительные действия:
<link rel="prefetch" href="/style.css" as="style" />
<link rel="preload" href="/style.css" as="style" />
<link rel="preconnect" href="https://example.com" />
<link rel="dns-prefetch" href="https://example.com" />
<link rel="prerender" href="https://example.com/about.html" />
Вкратце расскажем, что они делают и когда их использовать.
Перейти к: preload · prefetch · preconnect · dns-prefetch · prerender
preload
<link rel= "preload">
говорит браузеру как можно скорее загрузить и кэшировать ресурс (например, скрипт или таблицу стилей). Это полезно, когда ресурс понадобится через несколько секунд после загрузки страницы — и вы хотите ускорить процесс.Браузер ничего не делает с ресурсом после загрузки. Скрипты не выполняются, таблицы стилей не применяются. Ресурс просто кэшируется и немедленно предоставляется по запросу.
Синтаксис
<link rel="preload" href="/style.css" as="style" />
href
указывает на ресурс, который вы хотите скачать. as
может быть чем угодно, что можно скачать в браузере:style
для таблиц стилей,
script
для скриптов,
font
для шрифтов,
fetch
для ресурсов, загруженных с помощьюfetch()
илиXMLHttpRequest
,
- полный список см. на MDN.
Важно указать атрибут
as
– это помогает браузеру правильно расставлять приоритеты и планировать загрузку.Когда использовать
Используйте предзагрузку, когда ресурс понадобится в самое ближайшее время. Например:
- Нестандартные шрифты из внешнего файла:
<!-- index.html --> <link rel="stylesheet" href="index.css" /> /* index.css */ @font-face { src: url('comic-sans.woff2') format('woff2'); }
По умолчаниюcomic-sans.woff2
начнёт загружаться только после загрузки и разбораindex.css
. Чтобы не ждать так долго, можно загрузить шрифт раньше с помощью<link rel= "preload">
:
<link rel="preload" href="comic-sans.woff2" as="font" />
- Если вы разделяете свои стили согласно подходу Critical CSS на две части, критическую (для немедленного рендеринга) и некритическую:
<style> /* Inlined critical styles */ </style> <script> /* Custom JS that starts downloading non-critical styles */ loadCSS('/app/non-critical.css'); </script>
При таком подходе некритические стили начнут загружаться только при запуске JavaScript, что может произойти через несколько секунд после рендеринга. Вместо ожидания JS используйте<link rel= "preload">
, чтобы начать загрузку раньше:
<style> /* Inlined critical styles */ </style> <link rel="preload" href="/app/non-critical.css" as="style" /> <script> /* Custom JS that starts downloading non-critical styles */ loadCSS('/app/non-critical.css'); </script>
Не злоупотребляйте предзагрузкой. Если загружать всё подряд, сайт не ускорится волшебным образом, скорее наоборот, это помешает браузеру грамотно планировать работу.
Не путайте с префетчингом. Не используйте
<link rel= "preload">
, если вам не нужен ресурс сразу после загрузки страницы. Если он понадобится позже, например, для следующей страницы, то используйте <link rel= "prefetch">
.Подробности
Это обязательный тег для исполнения браузером (если он его поддерживает), в отличие от всех других тегов <link>, связанных с предварительной загрузкой. Браузер обязан загрузить ресурс, указанный в
<link rel="preload">
. В других случаях он может проигнорировать предварительную загрузку, например, если работает на медленном соединении.Приоритеты. Разным ресурсам (стили, скрипты, шрифты и т. д.), браузеры обычно назначают разные приоритеты, чтобы в первую очередь загружать самые важные ресурсы. В данном случае браузер определяет приоритет по атрибуту
as
. Для браузера Chrome можете посмотреть полную таблицу приоритетов.prefetch
<link rel= "prefetch">
просит браузер загрузить и кэшировать ресурс (например, скрипт или таблицу стилей) в фоновом режиме. Загрузка происходит с низким приоритетом, поэтому не мешает более важным ресурсам. Это полезно, если ресурс понадобится на следующей странице, а вы хотите заранее его кэшировать.Здесь тоже браузер ничего не делает с ресурсом после загрузки. Скрипты не выполняются, таблицы стилей не применяются. Ресурс просто кэшируется и немедленно предоставляется по запросу.
Синтаксис
<link rel="prefetch" href="/style.css" as="style" />
href
указывает на ресурс, который вы хотите скачать. as
может быть чем угодно, что можно скачать в браузере:style
для таблиц стилей,
script
для скриптов,
font
для шрифтов,
fetch
для ресурсов, загруженных с помощьюfetch()
илиXMLHttpRequest
,
- полный список см. на MDN.
Важно указать атрибут
as
— это помогает браузеру правильно расставлять приоритеты и планировать загрузку.Когда использовать
Для загрузки ресурсов с других страниц, если нужен ресурс с другой страницы, и вы хотите предварительно загрузить его, чтобы потом ускорить рендеринг этой страницы. Например:
- У вас интернет-магазин, и 40% пользователей уходят с главной страницы на страницу товара. Используйте
<link rel= "prefetch">
, загружая файлы CSS и JS для рендеринга страниц с продуктом.
- У вас одностраничное приложение, а разные страницы загружают разные пакеты. Когда пользователь посещает какую-то страницу, можно предварительно загрузить пакеты для всех страниц, на которые она ссылается.
Вероятно, этот тег можно безопасно использовать в любом объёме. Браузеры обычно планируют prefetch с наименьшим приоритетом, так что он никому не мешает. Только имейте в виду, что расходуется трафик пользователя, который может стоить денег.
Не для срочных запросов. Не используйте
<link rel= "prefetch">
, когда ресурс понадобится через несколько секунд. В этом случае применяйте <link rel= "preload">
.Подробности
Необязательный тег. Браузер не обязан следовать этой инструкции, он может проигнорировать её, например, на медленном соединении.
Приоритет в Chrome. В Chrome
<link rel= "prefetch">
обычно выполняется с минимальным приоритетом (см. полную таблицу приоритетов), то есть после загрузки всего остального.preconnect
<link rel= "preconnect">
просит браузер заранее подключиться к домену, когда вы хотите ускорить установку соединения в будущем.Браузер должен установить соединение, если извлекает какие-то ресурсы с нового стороннего домена. Например, если загружает шрифты Google Fonts, React из CDN или запрашивает ответ JSON с сервера API.
Установка нового соединения обычно занимает несколько сотен миллисекунд. Она производится один раз, но всё равно отнимает время. Если вы заранее установили соединение, то сэкономите время и быстрее загрузите ресурсы с этого домена.
Синтаксис
<link rel= "preconnect" href="https://api.my-app.com" />
href
указывает на доменное имя, для которого нужно определить IP-адрес. Можно указывать с префиксом (https://domain.com
) или без него (//domain.com
).Когда использовать
Используйте для доменов, которые скоро понадобятся для загрузки оттуда важного стиля, скрипта или изображения, но вы пока не знаете URL ресурса. Например:
- Ваше приложение размещается на
my-app.com
и делает AJAX-запросы кapi.my-app.com
: вы не знаете заранее конкретные запросы, потому что они делатся динамически из JS. Здесь вполне уместно использование тега для предварительного подключения к домену.
- Ваше приложение размещается на
my-app.com
и использует шрифты Google Fonts. Они загружаются в два этапа: сначала загружается файл CSS с доменаfonts.googleapis.com
, затем этот файл запрашивает шрифты сfonts.gstatic.com
. Вы не можете знать, какие конкретные файлы шрифтов изfonts.gstatic.com
вам понадобятся, пока не загрузите файл CSS, поэтому заранее мы можем только установить предварительное соединение.
Используйте этот тег, чтобы немного ускорить какой-то сторонний скрипт или стиль за счёт предварительной установки соединения.
Не злоупотребляйте. Установка и поддержание соединения — дорогостоящая операция как для клиента, так и для сервера. Используйте этот тег максимум для 4-6 доменов.
Подробности
Необязательный тег. Браузер не обязан следовать этой инструкции и может проигнорировать её, например, если уже установлено много соединений или в каком-то другом случае.
Что включает в себя процесс подключения. Для подключения к каждому сайту браузер должен выполнить следующие действия:
- Резолвинг DNS. Найти IP-адрес сервера (
216.58.215.78
) для указанного доменного имени (google.com
). - Рукопожатие TCP. Обмен пакетами (клиент → сервер → клиент), чтобы инициировать TCP-соединение с сервером.
- Рукопожатие TLS (только для сайтов HTTPS). Два раунда обмена пакетами (клиент → сервер → клиент → сервер → клиент), чтобы инициировать безопасный сеанс TLS.
Примечание: HTTP/3 улучшит и ускорит механизм рукопожатия, но он ещё далеко.
dns-prefetch
<link rel= "dns-prefetch">
просит браузер заранее выполнить резолвинг DNS для домена, если вы скоро будете подключаться к нему и хотите ускорить начальное соединение.Браузер должен определить IP-адрес домена, если будет извлекать какие-то ресурсы с нового стороннего домена. Например, загружать шрифты Google Fonts, React из CDN или запрашивать ответ JSON с сервера API.
Для каждого нового домена разрешение записи DNS обычно занимает около 20−120 мс. Это влияет только на загрузку первого ресурса с данного домена, но всё равно представляет задержку. Если осуществить разрешение DNS заранее, то мы сэкономим время и загрузим ресурс быстрее.
Синтаксис
<link rel= "dns-prefetch" href="https://api.my-app.com" />
href
указывает на доменное имя, для которого нужно установить IP-адрес. Можно указывать с префиксом (https://domain.com
) или без него (//domain.com
).Когда использовать
Используйте для доменов, которые скоро понадобятся для загрузки оттуда ресурсов, о которых браузер не знает заранее. Например:
- Ваше приложение размещается на
my-app.com
и делает AJAX-запросы кapi.my-app.com
: вы не знаете заранее конкретные запросы, потому что они делатся динамически из JS. Здесь вполне уместно использование тега для предварительного подключения к домену.
- Ваше приложение размещается на
my-app.com
, и использует шрифты Google Fonts. Они загружаются в два этапа: сначала загружается файл CSS с доменаfonts.googleapis.com
, затем этот файл запрашивает шрифты сfonts.gstatic.com
. Вы не можете знать, какие конкретные файлы шрифтов изfonts.gstatic.com
вам понадобится, пока не загрузите файл CSS, поэтому заранее мы можем только установить предварительное соединение.
Используйте этот тег, чтобы немного ускорить какой-то сторонний скрипт или стиль за счёт предварительной установки соединения.
Обратите внимание схожие характеристики на<link rel= "dns-prefetch"/>
и<link rel= "preconnect">
. Использовать их вместе для одного домена обычно не имеет смысла:<link rel= "preconnect">
уже включает в себя<link rel= "dns-prefetch"/>
и многое другое. Это можно оправдать в двух случаях:
- Вы хотите поддерживать старые браузеры.
<link rel= "dns-prefetch" />
поддерживается начиная с IE10 и Safari 5.<link rel= "preconnect">
некоторое время поддерживался в Chrome и Firefox, но был добавлен в Safari только в 11.1 и по-прежнему не поддерживается в IE/Edge. Если нужно поддерживать эти браузеры, используйте<link rel= "dns-prefetch" />
в качестве запасного варианта для<link rel= "preconnect">
.- Вы хотите ускорить подключение более чем к 4−6 доменам. Тег
<link rel= "preconnect">
не рекомендуется использовать более чем с 4−6 доменами, так как установка и поддержание соединения — дорогостоящая операция.<link rel= "dns-prefetch" />
потребляет меньше ресурсов, поэтому в случае необходимости используйте его.
Подробности
Необязательный тег. Браузер не обязан следовать этой инструкции, поэтому может не выполнять резолвинг DNS, например, если на странице много таких тегов или в каком-то другом случае.
Что такое DNS. Каждому серверу в интернете соответствует уникальный IP-адрес, который выглядит как
216.58.215.78
. В адресной строке браузера обычно вводится название сайта (например, google.com
), а серверы DNS (Domain Name System) сопоставляют его с IP-адресом сервера (216.58.215.78
).Чтобы определить IP-адрес, браузер должен выполнить запрос к DNS-серверу. Он занимает 20−120 мс при подключении к новому стороннему домену.
DNS кэшируется, хотя и не очень надёжно. Некоторые ОС и браузеры кэшируют DNS-запросы: это сэкономит время при повторных запросах, но на кэширование нельзя полагаться. В Linux оно обычно вообще не работает. У Chrome есть кэш DNS, но он живёт только минуту. Windows кэширует DNS-ответы в течение пяти дней.
prerender
<link rel= "prerender">
просит браузер загрузить URL-адрес и отобразить его на невидимой вкладке. Когда пользователь нажимает на ссылку, страница должна отобразиться немедленно. Это полезно, если вы уверены, что пользователь посетит определённую страницу, и хотите ускорить её отображение.Несмотря на исключительную эффективность этого тега (или из-за неё), в 2019 году
<link rel= "prerender">
плохо поддерживается основными браузерах. Подробнее см. ниже.Синтаксис
<link rel="prerender" href="https://my-app.com/pricing" />
href
указывает на URL, для который вы хотите запустить рендеринг в фоновом режиме.Когда использовать
Когда вы действительно уверены, что пользователь перейдёт на определённую страницу. Если у вас «туннель», по которому 70% посетителей страницы A переходят на страницу Б, то
<link rel= "prerender">
на странице А поможет очень быстро отобразить страницу Б.Не злоупотребляйте. Предварительный рендеринг чрезвычайно дорого обходится с точки зрения трафика и памяти. Не используйте
<link rel= "prerender">
более чем для одной страницы.Подробности
Необязательный тег. Браузер не обязан следовать этой инструкции и может проигнорировать её, например, на медленном соединении или при недостаточном объёме свободной памяти.
Ради экономии памяти Chrome не выполняет полный рендеринг, а только предзагрузку NoState. Это означает, что Chrome загружает страницу и все её ресурсы, но не делает рендеринг и не выполняет JavaScript.
Firefox и Safari вообще не поддерживают этот тег. Это не нарушает спецификацию, так как браузеры не обязаны выполнять данную инструкцию; но всё равно печально. Баг реализации в Firefox был открыт в течение семи лет. Есть сообщения, что Safari тоже не поддерживает этот тег.
Резюме
Используйте:
<link rel= "preload">
— когда вам понадобится ресурс через несколько секунд
<link rel= "prefetch">
— когда понадобится ресурс на следующей странице
<link rel= "preconnect">
— когда вы знаете, что вам скоро понадобится ресурс, но вы ещё не знаете его полный URL
<link rel= "dns-prefetch">
— аналогично, когда вы знаете, что вам скоро понадобится ресурс, но вы ещё не знаете его полный URL (для старых браузеров)
<link rel= "prerender">
— когда вы уверены, что пользователи перейдут на определённую страницу, и хотите ускорить её отображение