Асинхронная и отложенная загрузка JavaScript
Приветствую, друзья! Знаете ли вы, что загрузка JavaScript является одним из самых узких мест в производительности сайта? Сегодня моя основная задача — объяснить что такое асинхронная загрузка скрипта и каким образом она влияет на быстродействие и производительность сайта.
Браузер, загружающий тег <script>
, останавливает рендеринг страницы до тех пор, пока не загрузится и не исполнится скрипт. Страница заблокирована и браузер пару секунд не отвечает на действия пользователя. Время задержки зависит от нескольких факторов:
- конфигурации хостинга,
- скорости интернет-соединения,
- размера файла и других…
По этой причине анализатор скорости загрузки сайта PageSpeed Insights рекомендует удалить из верхней части страницы код JavaScript, блокирующий её отображение. Хорошей практикой является размещение скриптов в нижней части сайта, например, перед закрывающим тегом </body>
или настройка асинхронной загрузки.
Если код скрипта влияет на отображение верхней части сайта — не выносите его в отдельный файл, а встраивайте непосредственно в HTML.
JS может изменить содержимое сайта и даже перенаправить на другой URL-адрес. В таком случае подключение скрипта в конце документа приведёт к эффекту «подергивания» страницы, подгружая новые или изменяя существующие элементы в верхней части.
Давайте разберёмся, что из себя представляет асинхронная и отложенная работа JavaScript и какая принципиальная разница между атрибутами async
и defer
. Но вначале рассмотрим последовательность обработки документа при обычном подключении тега <script>
.
<script src="example.js"></script>
В наглядном примере я буду использовать следующие условные обозначения:
— обработка страницы | |
— загрузка скрипта | |
— выполнение скрипта |
Таким образом, последовательность обработки документа происходит по следующей схеме:
Разбор HTML-кода прерывается на время загрузки и выполнения скрипта, после чего продолжается. Отображение веб-страницы происходит с задержкой.
Атрибут defer
Атрибут defer
позволяет браузеру начать загрузку js-файлов параллельно, не останавливая дальнейшую обработку страницы. Их выполнение происходит после полного разбора объектной модели документа (от англ. Document Object Model, сокращенно DOM), при этом браузер гарантирует последовательность на основе порядка подключения файлов.
<script defer src="example.js"></script>
Схема последовательности обработки:
Это отложенная загрузка. Данный атрибут рекомендуется применять при подключении нескольких JS файлов, при условии что один скрипт зависит от другого и вам важна последовательность их выполнения.
Атрибут async
Поддержка атрибута async
появилась в HTML5, он разрешает браузеру загружать js-файлы параллельно и выполнять сразу после загрузки, не дожидаясь обработки остальной части страницы.
<script async src="example.js"></script>
Схема последовательности обработки:
Это асинхронная загрузка. Атрибут рекомендуется применять для таких скриптов, которые не оказывают значительного влияния на отображение документа. К ним относятся счётчики сбора статистики (Google Analytics, Яндекс Метрика), коды рекламных сетей (Рекламная сеть Яндекса, Google AdSense), кнопки социальных сетей и так далее.
Скорость загрузки сайта — один из факторов ранжирования в Google.
Асинхронное подключение JavaScript снижает время загрузки страниц за счёт отсутствия задержки. Наряду с этим я рекомендую сжимать и объединять js-файлы в один, например, с помощью библиотеки Minify. Пользователям нравятся быстрые сайты 😎
Отложенная загрузка изображений при помощи JavaScript | Битрикс-веб-мастер
- Главная
- Банк знаний
- JavaScript
- Отложенная загрузка изображений при помощи JavaScript
Если на странице очень много изображений — это очень плохо для скорости загрузки страниц. Гугловский pagespeed при проверке сайта в 90% случаев находит самую большую проблему именно в изображениях. Пробовал использовать скрипты оптимизации — не помогают. pagespeed настроенный на сервере — слишком сильно ухудшает качество. Решением проблемы стал скрипт отложенной загрузки изображений.
Основная идея заключается в том, что все необходимые данные для загрузки изображения, а именно путь к изображению мы будем хранить в самом теге img изображения, но не в атрибуте src, а в атрибуте data-src. Вдобавок, в каждый тег изображения, загрузку которого требуется отложить мы добавим класс, например delay, что бы потом была возможность доступа к нему из JavaScript.
<img data-src="/путь/к/изображению.png" />
Если не указать атрибуты width и height в теге изображения при загрузке страницы, будет ломаться верстка. Так же советую обязательно прописать атрибут alt, (но это вам и так любой сеошник скажет) пока все хозяйство будет грузиться пользователь будет их лицезреть.
Сама функция отложенной загрузки изображений — простая и состоит буквально из нескольких строк кода. В функции проверяется свойство документа document.onreadystatechange — которое изменяется по мере загрузки страницы, и как только оно становиться «complete» — это означает что документ загружен. Сразу после этого функция обходит массив изображений, который мы ей передали, и у каждого элемента просто переписывает значение пути к изображению из атрибута data-src в атрибут src:
/** * @param {DOMNodeList|HTMLElement[]} набор html-элементов-картинок. */ function delayPics (picsArray) { /* Это событие происходит каждый раз при изменении onreadystatechange */ document.onreadystatechange = function(e) { /* Когда документ загрузился - начинаем загрузку изображений: */ if ("complete" === document.readyState) { for (var i = 0; iДанная функция принимает лишь один аргумент - массив изображений, загрузку которых нам надо отложить.
Вызов функции имеет следующий вид:
// Используем getElementsByClassName для выбора картинок по имени класса delayPics (document.getElementsByClassName("delay"))Готово! Теперь изображения будут подгружаться после загрузки всего сайта. Единственный недостаток - эти изображения не будут индексироваться поисковиками. Но это решается добавлением в карту сайта изображений (мой модуль генерации карты сайта это умеет делать)
Количество показов: 3944
Источник: http://php-zametki.ru/javascript-laboratoriya/134-otlozhennaya-zagruzka-izobrazhenij-pri-pomoshhi-javascript.html
07.06.2017
Возврат к списку
Если вам была полезна статья можете отблагодарить автора:
Подайте заявку на разработку сайта на базе готового решения от компании
1С-Битрикс или одного из партнеров компании.
Максимально подробно опишите, чему будет посвящен сайт, если это интернет-магазин — что он
будет
продавать,
нужна ли мультиязычность, будут ли разные типы цен (розница, опт, крупный опт), будет ли
интеграция с 1С,
будет ли выгрузка товаров на различные торговые площадки. ..
Вы можете подать заявку на сопровождение вашего сайта на базе 1С-Битрикс. Сопровождение включает в себя: проверка актуальности обновлений сайта, проверка актуальности резервной копии, консультации по сайту. Опишите в заявке, какие еще объемы планируются на сопровождении и на какой срок вы планируете заключить договор на сопровождение — мы подберем подходящий вам бюджет на сопровождение
Вы можете подать заявку на выполнение определенного объема работ по сайту. Опишите в заявке объем работ. Это может быть разработка какого-то нового функционала, доработки по имеющемуся функционалу, доработки под требования сео-специалистов. На основании заявки вам будет сформирован бюджет работ, а также названы сроки на выполнение тех или иных работ.
Ленивая загрузка — веб-производительность
Ленивая загрузка — это стратегия идентификации ресурсов как неблокирующих (некритических) и загрузки их только при необходимости. Это способ сократить длину критического пути рендеринга, что приводит к сокращению времени загрузки страницы.
Ленивая загрузка может происходить в разные моменты приложения, но обычно это происходит при некоторых действиях пользователя, таких как прокрутка и навигация.
По мере развития Интернета мы наблюдаем огромный рост количества и размера ресурсов, отправляемых пользователям. В период с 2011 по 2019 год, средний вес ресурса увеличился с ~ 100 КБ до ~ 400 КБ для настольных компьютеров и с ~ 50 КБ до ~ 350 КБ для мобильных устройств. В то время как размер изображения увеличился с ~ 250 КБ до ~ 900 КБ на настольных компьютерах и с ~ 100 КБ до ~ 850 КБ на мобильных устройствах.
Один из методов, который мы можем использовать для решения этой проблемы, — сократить длину критического пути рендеринга за счет ленивой загрузки ресурсов, которые не являются критическими для первого рендеринга.
Практический пример: вы попадаете на домашнюю страницу сайта электронной коммерции со ссылкой на страницу/раздел корзины, и ни один из ресурсов страницы корзины (например, JavaScript, CSS и изображения) не загружен.
Ленивая загрузка может применяться к нескольким ресурсам и с помощью нескольких стратегий.
Общие
Разделение кода
JavaScript, CSS и HTML можно разделить на более мелкие фрагменты. Это позволяет заранее отправлять минимальный код, необходимый для предоставления ценности, что сокращает время загрузки страницы. Остальные могут быть загружены по запросу.
- Разделение точек входа: разделяет код по точкам входа в приложении
- Динамическое разделение: разделяет код, в котором используются операторы динамического импорта()
JavaScript
Модуль типа сценария
Любой тег сценария с type="module"
рассматривается как модуль JavaScript и по умолчанию откладывается.
CSS
По умолчанию CSS рассматривается как блокирующий рендеринг ресурс, поэтому браузер не будет рендерить обработанный контент, пока не будет создан CSSOM. CSS должен быть тонким, доставляться как можно быстрее, а используемым типам мультимедиа и запросам рекомендуется разблокировать рендеринг.
Для этого можно выполнить некоторые оптимизации CSS.
Шрифты
По умолчанию запросы шрифтов откладываются до тех пор, пока не будет построено дерево рендеринга, что может привести к задержке рендеринга текста.
Можно переопределить поведение по умолчанию и предварительно загрузить ресурсы веб-шрифтов, используя
, свойство CSS font-display и API загрузки шрифтов.
См. также: Ссылка на элемент.
Изображения и фреймы
Очень часто веб-страницы содержат много изображений, которые влияют на использование данных и скорость загрузки страницы. Большинство этих изображений находятся за пределами экрана (некритические), и для их просмотра требуется взаимодействие с пользователем, например прокрутка.
Загрузка атрибута
Атрибут загрузки
в элементе
(или атрибут загрузки
в элементе
) может использоваться для указания браузеру отложить загрузку изображений/фреймов, которые за пределами экрана, пока пользователь не прокрутит их до нужного места.
![]()
Событие
load
срабатывает, когда загружено все нетерпеливо загруженное содержимое; в то время вполне возможно (или даже вероятно), что могут быть лениво загруженные изображения, которые находятся в визуальном окне просмотра, но еще не загружены.
Вы можете определить, закончилась ли загрузка данного изображения, изучив значение его логического значения
полное свойство
.
Полифилл
Включите этот полифилл, чтобы обеспечить поддержку старых и в настоящее время несовместимых браузеров: загрузка-атрибут-полифилл.
Intersection Observer API
Intersection Observer позволяют пользователю узнать, когда наблюдаемый элемент входит или выходит из области просмотра браузера.
Обработчики событий
Когда совместимость с браузером имеет решающее значение, есть несколько вариантов:
обозреватель полифилловых пересечений
резервный вариант для обработчиков событий прокрутки, изменения размера или изменения ориентации, чтобы определить, находится ли конкретный элемент в области просмотра
Блокировка CSS
Спецификация |
---|
Стандарт HTML # lazy-loading-attributes |
Оптимизация загрузки и рендеринга
Ленивая загрузка изображений и видео
Обнаружили проблему с содержанием этой страницы?
Отредактируйте страницу на GitHub.
Сообщить о проблеме с содержимым.
Посмотреть исходный код на GitHub.
Хотите принять участие?
Узнайте, как внести свой вклад.
Последний раз эта страница была изменена участниками MDN.
Критический путь отрисовки — веб-производительность
Критический путь рендеринга — это последовательность шагов, которые браузер выполняет для преобразования HTML, CSS и JavaScript в пиксели на экране. Оптимизация критического пути рендеринга повышает производительность рендеринга.
Критический путь рендеринга включает в себя объектную модель документа (DOM), объектную модель CSS (CSSOM), дерево рендеринга и макет.
Объектная модель документа создается при анализе HTML. HTML может запросить JavaScript, который, в свою очередь, может изменить DOM. HTML включает или делает запросы на стили, которые, в свою очередь, создают объектную модель CSS.
Движок браузера объединяет их для создания дерева рендеринга. Макет определяет размер и расположение всего на странице. Как только макет определен, пиксели рисуются на экране. Оптимизация критического пути рендеринга сокращает время до первого рендеринга. Понимание и оптимизация критического пути рендеринга важны для обеспечения того, чтобы перекомпоновки и перерисовки могли происходить со скоростью 60 кадров в секунду, чтобы обеспечить эффективное взаимодействие с пользователем и избежать рывков.
Веб-производительность включает в себя запросы и ответы сервера, загрузку, сценарии, рендеринг, компоновку и отрисовку пикселей на экране.
Запрос веб-страницы или приложения начинается с запроса HTML. Сервер возвращает HTML — заголовки ответа и данные. Затем браузер начинает анализировать HTML, преобразовывая полученные байты в дерево DOM. Браузер инициирует запросы каждый раз, когда находит ссылки на внешние ресурсы, будь то таблицы стилей, скрипты или встроенные ссылки на изображения.
Некоторые запросы блокируются, что означает, что синтаксический анализ остальной части HTML останавливается до тех пор, пока не будет обработан импортированный ресурс. Браузер продолжает анализировать HTML, делая запросы и создавая DOM, пока не дойдет до конца, после чего он строит объектную модель CSS. Когда DOM и CSSOM завершены, браузер строит дерево рендеринга, вычисляя стили для всего видимого содержимого. После того, как дерево рендеринга завершено, происходит компоновка, определяющая расположение и размер всех элементов дерева рендеринга. После завершения страница визуализируется или «рисуется» на экране. Объектная модель документа
Построение DOM является добавочным. Ответ HTML превращается в токены, которые превращаются в узлы, которые превращаются в дерево DOM. Один узел DOM начинается с токена startTag и заканчивается токеном endTag. Узлы содержат всю необходимую информацию об элементе HTML. Информация описывается с помощью токенов. Узлы подключаются к дереву DOM на основе иерархии токенов.
Если другой набор токенов startTag и endTag находится между набором startTag и endTags, у вас есть узел внутри узла, именно так мы определяем иерархию дерева DOM.
Чем больше количество узлов, тем дольше будут происходить следующие события на критическом пути рендеринга. Мера! Несколько дополнительных узлов не будут иметь большого значения, но имейте в виду, что добавление большого количества дополнительных узлов повлияет на производительность.
Объектная модель CSS
Модель DOM содержит все содержимое страницы. CSSOM содержит всю информацию о том, как стилизовать DOM. CSSOM похож на DOM, но отличается. В то время как конструкция DOM является инкрементной, CSSOM — нет. CSS блокирует рендеринг: браузер блокирует рендеринг страницы до тех пор, пока не получит и не обработает весь CSS. CSS блокирует отрисовку, потому что правила могут быть перезаписаны, поэтому содержимое не может быть отрисовано, пока CSSOM не будет завершен.
В CSS есть собственный набор правил для определения действительных токенов.
Помните, что C в CSS означает «Каскад». Правила CSS каскадируются. Поскольку синтаксический анализатор преобразует токены в узлы, узлы-потомки наследуют некоторые стили родителя. Функции инкрементной обработки не применяются к CSS, как к HTML, поскольку последующие правила могут иметь приоритет над предыдущими. Объектная модель CSS строится по мере синтаксического анализа CSS, но ее нельзя использовать для построения дерева рендеринга до тех пор, пока оно не будет полностью проанализировано, поскольку стили, которые будут перезаписаны при более позднем синтаксическом анализе, не должны отображаться на экране.
С точки зрения производительности селекторов менее конкретные селекторы работают быстрее, чем более конкретные. Например, .foo {}
быстрее, чем .bar .foo {}
, потому что, когда браузер находит .foo
, во втором сценарии он должен просмотреть DOM, чтобы проверить, есть ли .foo
. предок .bar
. Более конкретный тег требует больше работы от браузера, но вряд ли стоит оптимизировать этот штраф.
Если вы измерите время, необходимое для синтаксического анализа CSS, вы будете поражены тем, насколько на самом деле быстры браузеры. Более конкретное правило дороже, потому что оно должно проходить через большее количество узлов в дереве DOM, но эти дополнительные затраты, как правило, минимальны. Сначала измерьте. Оптимизируйте по мере необходимости. Специфичность, скорее всего, не ваш самый низкий висящий фрукт. Когда дело доходит до CSS, улучшения оптимизации производительности селекторов будут всего за микросекунды. Существуют и другие способы оптимизации CSS, такие как минимизация и разделение отложенного CSS на неблокирующие запросы с помощью медиа-запросов.
Дерево рендеринга
Дерево рендеринга захватывает как содержимое, так и стили: деревья DOM и CSSOM объединяются в дерево рендеринга. Чтобы построить дерево рендеринга, браузер проверяет каждый узел, начиная с корня дерева DOM, и определяет, какие правила CSS присоединены.
Дерево рендеринга захватывает только видимое содержимое.
Раздел заголовка (обычно) не содержит никакой видимой информации и поэтому не включается в дерево рендеринга. При наличии дисплея : нет;
для элемента, ни он, ни его потомки не находятся в дереве рендеринга.
Компоновка
После построения дерева рендеринга становится возможной компоновка. Макет зависит от размера экрана. Шаг компоновки определяет, где и как элементы располагаются на странице, определяя ширину и высоту каждого элемента, а также их расположение по отношению друг к другу.
Какова ширина элемента? Элементы уровня блока по определению имеют ширину по умолчанию, равную 100% ширины их родителя. Элемент шириной 50% будет составлять половину ширины своего родителя. Если не указано иное, тело имеет ширину 100%, что означает, что оно будет составлять 100% ширины области просмотра. Эта ширина устройства влияет на макет.
Метатег области просмотра определяет ширину области просмотра макета, влияя на макет. Без этого браузер использует ширину области просмотра по умолчанию, которая в полноэкранных браузерах по умолчанию обычно составляет 960 пикселей.
В полноэкранных браузерах по умолчанию, таких как браузер вашего телефона, установив
, ширина будет шириной устройства вместо ширины области просмотра по умолчанию. . Ширина устройства изменяется, когда пользователь поворачивает свой телефон между альбомным и портретным режимами. Макет происходит каждый раз, когда устройство поворачивается или размер браузера иным образом изменяется.
DOM влияет на производительность макета — чем больше количество узлов, тем больше времени занимает макет. Макет может стать узким местом, приводя к рывкам, если это необходимо во время прокрутки или других анимаций. Хотя задержка в 20 мс при загрузке или изменении ориентации может быть хорошей, она приведет к рывкам при анимации или прокрутке. При каждом изменении дерева рендеринга, например добавлении узлов, изменении содержимого или обновлении стилей блочной модели на узле, происходит компоновка.
Чтобы уменьшить частоту и продолжительность событий компоновки, пакетные обновления и избежать анимации свойств блочной модели.
Краска
Последний шаг — рисование пикселей на экране. После создания дерева рендеринга и компоновки пиксели можно отрисовывать на экране. При загрузке рисуется весь экран. После этого будут перерисованы только затронутые области экрана, так как браузеры оптимизированы для перерисовки минимально необходимой области. Время отрисовки зависит от того, какие обновления применяются к дереву рендеринга. Хотя рисование — это очень быстрый процесс, и поэтому, вероятно, не самое эффективное место, на котором следует сосредоточиться для повышения производительности, важно помнить, что при измерении того, сколько времени может занять кадр анимации, необходимо учитывать время как макета, так и повторного рисования. Стили, применяемые к каждому узлу, увеличивают время отрисовки, но удаление стиля, который увеличивает отрисовку на 0,001 мс, может не дать вам максимальной отдачи от оптимизации. Не забудьте сначала измерить. Затем вы можете определить, должно ли это быть приоритетом оптимизации.