Ленивая загрузка (Lazy loading) для улучшения производительности
Lazy loading (ленивая загрузка) - это стратегия, направленная на определение ресурсов как неблокирующих (не критических) для того, чтобы отложить загрузку этих ресурсов на тот момент, когда они действительно необходимы. Так можно сократить длину критических этапов рендеринга, что приводит к уменьшению времени загрузки приложения.
В зависимости от конкретной ситуации, ленивая загрузка может быть запущена в разные моменты работы приложения, но обычно это происходит во время взаимодействия пользователя и системы, например, при скроллинге или навигации.
С ростом web-приложений объем и размеры ресурсов, отправляемых клиентскому приложению, значительно возросли. С 2011 по 2019 год медианный размер ресурсов увеличился с ~100KB до ~400KB для настольных компьютеров и с ~50KB до ~350KB для мобильных устройств. Размер изображений также увеличился с ~250KB до ~900KB для настольных компьютеров и с ~100KB до ~850KB для мобильных устройств.
Такое увеличение объемов ресурсов приводит к увеличению времени загрузки приложения. Одним из способов сокращения времени загрузки является отложенная загрузка ресурсов, которые не являются критически важными для приложения. Например, если пользователь посещает интернет-магазин, состоящий из списка товаров и корзины, ему не нужны изображения товаров, которые в данный момент находятся за пределами экрана, и также не нужно грузить все данные о содержимом корзины, пока пользователь не перейдет к ней.
Техника ленивой загрузки (Lazy loading
) может применяться к различным ресурсам и реализовываться разными подходами.
Общий подход
Разделение кода (code splitting
) может использоваться для разбиения JavaScript, CSS и HTML на меньшие части, называемые чанками (chunks
). Вместо отправки всего приложения во время первоначальной загрузки, можно отправлять только необходимые части, например, только каркас разметки. Данные для заполнения этого каркаса могут быть загружены позже, например, с помощью AJAX
. Существуют два вида разделения кода:
- Разделение по точкам входа (entrypoint)
- Динамическое (dynamic import())
JavaScript Любой тег скрипта с атрибутом type="module"
рассматривается как модуль JavaScript, и его загрузка откладывается по умолчанию.
CSS
По умолчанию CSS считается ресурсом, блокирующим рендеринг (render blocking). Это означает, что браузер не будет отображать контент до тех пор, пока не будет построена объектная модель CSS (CSSOM). Поэтому CSS-файл должен быть небольшим, чтобы он был доставлен как можно быстрее. Рекомендуется использовать медиавыражения, чтобы вместо одного большого CSS-файла загружать специализированные.
<link href="style.css" rel="stylesheet" media="all">
<link href="portrait.css" rel="stylesheet" media="orientation:portrait">
<link href="print.css" rel="stylesheet" media="print">
Кроме того, для ускорения загрузки CSS можно использовать оптимизации (CSS optimizations).
Шрифты
По умолчанию загрузка шрифтов откладывается до тех пор, пока дерево рендера не будет полностью сформировано. Это может вызвать задержку в появлении текста на странице.
Если нужно, чтобы шрифты загружались заранее, то можно переопределить это поведение с помощью <link rel="preload">
, CSS свойства font-display
или API загрузки шрифтов (Font Loading API).
Изображения
На веб-страницах обычно содержится много изображений, загрузка которых занимает много времени и может замедлить скорость загрузки страницы. Большинство этих изображений находятся вне области видимости экрана и не являются критическими для взаимодействия пользователя с страницей (non-critical). Для просмотра таких изображений пользователю необходимо прокрутить страницу.
Чтобы уменьшить время загрузки страницы, можно использовать атрибут loading
для элемента <img>
или <iframe>
(loading
для <iframe>
). Этот атрибут указывает браузеру отложить загрузку изображения/фрейма до тех пор, пока пользователь не проскроллит до него.
Пример использования:
<img src="image.jpg" loading="lazy" alt="..." />
<iframe src="video-player.html" loading="lazy"></iframe>
Событие load
происходит, когда все остальные необходимые ресурсы загружены. В этот момент, даже если пользователь прокрутит до изображения и оно будет находиться в области видимости, оно может не загрузиться. Чтобы проверить, было ли изображение загружено, можно использовать булево значение complete.