Асинхронная загрузка JavaScript - ускоряем загрузку страниц. Добавление CSS

С ростом скорости интернет соединения и увеличении мощности не только десктопных, но и мобильных устройств веб страницы стают более "тяжелыми". Количество и размер подключаемых файлов растет: JavaScript файлы, css файлы, изображения, виджеты сторонних сайтов, iframe. На данный момент специфика работы браузеров такая, что при загрузке js файла блокируется отривсовка до того момента, пока скрипт не выполниться. Современные браузеры в фоновом режиме будут парсить документ и скачивать скрипты и стили, но отрисовка будет заблокирована. Сравнение сетевых параметров для различных браузеров можно посмотреть на browserscope.org . Мы не можем устранить блокировку полностью, но можем оптимизировать серверную и клиентскую часть приложения, что бы блокировка отрисовки занимала наименьший промежуток времени.

Решения для серверной части:
- Уменьшить размер передаваемых файлов
- Использовать CDN
- Вынести статические файлы на отдельный домен или под домен, таким образом увеличить количество одновременных соединений браузера.
- Включить сжатие передаваемых файлов(gzip)

Решения для клиентской части:
- Уменьшить количество запросов.
- Кэшировать файлы на стороне клиента с помощью заголовков Expires и Etags.
- Использовать общедоступные CDN(Google CDN, Yandex CDN). Таким образом, существует вероятность, что файл с общедоступного CDN уже будет храниться в кеше браузера.

Одним из способов оптимизации скорости загрузки сайта является асинхронная загрузка файлов, которая не блокирует отрисовку.

Скрипт асинхронной загрузки JavaScript:

(function() { var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "URL файла"; document.getElementsByTagName("head").appendChild(script); })();

Если JavaScript нужно выполнить после загрузки всей страницы, включая содержание, изображения, стилевые файлы и внешние скрипты, то к загрузчику нужно добавить отслеживания события onload.

If (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); }

Скрипт асинхронной загрузки JavaScript с учетом события onload (function() { function async_load(){ var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "URL файла"; document.getElementsByTagName("head").appendChild(script); } if (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); } })();

Но это единичный случай, когда требуется загрузка одного файла. Часто на практике подключается множество файлов.

Скрипт асинхронной загрузки множества подключаемых JavaScript файлов (function() { function async_load(){ [ "URL_файла_1.js", "URL_файла_2.js", "URL_файла_3.js" ].forEach(function(src) { var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = src; document.getElementsByTagName("head").appendChild(script); }); } if (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); } })();

Но в такой реализации есть минус - скрипты будут загружаться в произвольном порядке и соответсвенно выполнятся они будут произвольно во времени. Данный скрипт асинхронной загрузки идеально подходит, если выполнение JavaScript файлов не зависят один от другого и не зависит от DOM. В обратном случае его использование может привести к ошибкам на странице или непредвиденному результату выполнения. Для последовательного выполнения, но асинхронной загрузки, нужно указать async=false, тогда файлы будут скачиваться в произвольном порядке, но выполняться по очереди.

HTML 5. Асинхронная загрузка JavaScript

Стандарт HTML 5 поддерживает асинхронную загрузку JavaScript. Это можно сделать путем добавления ключевого слова async или defer. Например:

Скрипт, который подключен с атрибутом defer выполнится не нарушая порядок выполнения по отношению к остальным скриптам и его выполнение произойдет после полной загрузки и парсинга страницы, но перед тем, как вызовется DOMContentLoaded.

Скрипт, который подключен с атрибутом async выполнится при первой возможности после полной загрузки, но при этом не ожидает окончания парсинга документа и до загрузки объекта window. Браузеры не гарантируют выполнение скриптов в том же порядке в котором они подключены.

Библиотеки для асинхронной загрузки JavaScript

RequireJS - модуль загрузки JavaScript. Оптимизирован под браузеры, но он может использоваться в других средах, таких как Node, Rhino.

Require(["script"], function(script) { console.log("start after load script.js"); });

extsrc.js - библиотека, которая запускает скрипты на выполнение после того, как страница загрузится и отобразится пользователю. Работает корректно с document.write.

yepnope.js - позволяет совершать асинхронную загрузку JavaScript и CSS файлов.

Yepnope([ "script.js", "style.css" ]);

Простой способ загрузки JavaScript скриптов

Оказывается, что на практике добиться оптимальной кросс браузерной загрузки JavaScript скриптов, которые не блокируют отображение сложно, а порой невозможно. Наиболее оптимальный способом является добавление в конец документа перед закрывающимся тегом body. Из за ограничения разных браузеров и самого HTML такой вариант загрузки, который не блокирует отображение, можно считать наиболее простой.

Все мои мысли были направлены на решение основной проблемы:

В общем случае [при использовании data:URL], загрузка страницы не ускорится, а даже может замедлиться, потому что фоновые картинки (включенные через data:URL) будут грузиться в один поток, а не в несколько при обычном использовании спрайтов. Если фоновых картинок достаточно много (несколько десятков Кб), то это окажется существенным.

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

Постановка задачи

При использовании data:URL итоговый CSS-файл занимает довольно большой объем (фактически, размер всех картинок*1,2...1,5 + базовый CSS). И это в виде архива. Если файл не заархивирован, то его дополнительный размер увеличивается многократно (в 2,5-3 раза относительно размера всех фоновых изображений), но это не так существенно, ибо пользователей с отключенным сжатием для CSS-файлов сейчас единицы.

Что нам, фактически, нужно? Во-первых, нужно разделить весь массив CSS-правил на относящиеся к фоновым изображениям и не относящиеся. Во-вторых, сообщить браузерам, что они могут отобразить страницу без первого массива правил (ведь если в нем содержатся только фоновые изображения, то они могут и подождать чуть-чуть).

Чего мы таким образом добиваемся? Фактически, используя такой подход, мы создаем другой контейнер для фоновых изображений (не ресурсное изображение, а CSS-файл), который удобнее использовать в большинстве случаев. Мы объединяем все фоновые картинки не через CSS Sprites, а через data:URL, и можем загрузить их все одним файлом (в котором каждая картинка будет храниться совсем отдельно). При этом избегаем любых проблем с позиционированием фона.

Теоретическое решение

Все гениальное просто, поэтому мы можем загружать в начале странице легкий-легкий CSS-файл (безо всяких фоновых изображений, только базовые стили, чтобы только отобразить страницу корректно), потом по комбинированному window.onload грузить в 2-4 потока динамические файлы стилей.

Возможные минусы: после загрузки каждого дополнительного CSS-файла будет перерисовка страницы. Если таких файлов всего 1 или 2, то отображение страницы произойдет значительно быстрее.

Почему мы не распараллелим загрузку файлов стилей в самом начале документа? Потому что два файла будут загружаться медленнее, чем один. К тому же мы ратуем за максимально быстро отображение страницы в браузере пользователя, поэтому исходный объем загружаемого CSS должен быть минимальным (можно также рассмотреть варианты по включению его в сам HTML).

На практике

На практике все оказалось не сильно сложнее. Мы загружаем в head страницы (до вызовов любых внешних файлов) наш «легкий» CSS:

А затем добавляем в комбинированный window.onload (в самое начало) создание нового файла стилей, который дополняет уже загрузившийся фоновыми изображениями:

Function combinedWindowOnload() { load_dynamic_css("background-images.css"); ... }

В результате мы имеем максимально быстрое отображение страницы, а затем стадию пост-загрузки, которая вытянет и с сервера все дополнительные картинки (тут уже сам браузер постарается), стилевые правила и скрипты.

А доступность?

Внимательные читатели уже заготовили вопрос: а что, если у пользователя отключен JS? Ну, тут должно быть все просто: мы добавляем соответствующий noscript для поддержки таких пользователей.

С маленьким нюансом: noscript не может находиться в head , а link не может находиться в body . Если мы соблюдаем стандарты (все же иногда лучше довериться профессионалам и не ставить браузеры в неудобное положение, когда они встретятся с очередным отклонением от спецификации), то стоит искать обходные пути.

После небольших экспериментов с коллекцией styleSheets и другими DOM-объектами, было выделено следующее изящное решение, обеспечивающее работу схемы во всех браузерах (замечание: после многоличсленных экспериментах было решено остановиться на HTML-комментариях: они оказались наилучшим способом запретить загрузку указанного CSS-файла):

/* если мы сможем создать динамический файл стилей */ if (document.getElementsByTagName) { /* то добавляем в загрузку облегченную версию */ document.write("\x3clink href="light-light.css" rel="stylesheet" type="text/css" media="all"/>"); /* после этого начинаем HTML-комментарий */ document.write("\x3c--"); }

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

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

Грабли, грабли, грабли...

В ходе тестирования в Internet Explorer обнаружилось, что если добавлять файл стилей сразу параллельно со скриптами (в функции, которая для него срабатывает по onreadystatechange), то IE «морозит» первоначальную отрисовку страницы (т.е. показывает белый экран), пока не получит «свеженький» файл стилей. Для него пришлось вставить фиктивную задержку следующим образом:

SetTimeout("load_dynamic_css("background-images.css")",0);

В Safari же логика отображения страницы в зависимости от загружаемых файлов отличается ото всех браузеров. Подробнее можно прочитать эту заметку о FOUC проблеме и возможных решениях . Если в двух словах, то можно жестко определить начальный набор файлов, необходимых для отображения страницы на экране (HTML/CSS/JS), а можно начать загружать все файлы в порядке приоритетности (и выполняя все их зависимости) и проверять время от времени, можно ли уже отобразить страницу (выполняя все вычисления в фоновом режиме без обновления экрана). В общем, у Safari второй подход, поэтому ничего лучше выноса загрузки динамического CSS-файла с фоновыми картинками после срабатывания window.onload (который, на самом деле, срабатывает раньше, чем во всех остальных браузерах) придумать не удалось. Зато первоначальная картинка в браузере появляется быстрее.

Итак, если брать сразу комбинированный window.onload и добавлять в него загрузку стилей, то получится примерно такая конструкция:

/* объявляем функцию по динамической загрузке стилей и скриптов первый параметр - путь к файлу, второй - тип файла К сожалению, функция объявлена глобальна */ function loadDynamic (src,type){ var node=document.createElement(type?"link":"script"); node = document.getElementsByTagName("head").appendChild(node); /* если передаем второй параметр, то это таблица стилей */ if(type){ node.setAttribute("rel","stylesheet"); node.setAttribute("media","all") } node.setAttribute("type","text/"+(type?"css":"javascript")); node.setAttribute(type?"href":"src",src) } (function(){ /* немного модифицированная версия обработчика */ function combinedWindowOnload(){ if(arguments.callee.done){return} arguments.callee.done=true; if(document.getElementsByTagName){ /* если не Safari, то загружаем CSS с фоновыми изображениями динамически */ if(!/WebKit/i.test(navigator.userAgent)){ /* для обхода IE добавляем псевдо-задержку */ setTimeout("loadDynamic("background-images.css",1)",0); } /* ставим на поток загрузку всех наших скриптов */ loadDynamic("some_scripts.js"); } } /* дальше идет стандартный кроссбраузерный код с */ ... /* навешиваем на window обработчик по событию Onload, спасибо lusever за компактный вид */ window(/*@cc_on "on"+@*/"load",function(){ /* если Safari, то загружаем наконец этот CSS */ if(/WebKit/i.test(navigator.userAgent)){ loadDynamic("background-images.css",1); } /* добавочный вызов WindowOnload для "старых" браузеров */ combinedWindowOnload() },false) })()

Выигрыш

При наличии у вас большого количества маленьких декоративных фоновых изображений (например, для на каждой странице используется от 30 до 40 различных картинок, общий объем которых составляем порядка 30Кб), которые к тому же могут повторяться по различных направлениям, может быть очень удобно объединить их все в один файл, который загружать после отображения страницы на экране.

Описанная техника (кроссбраузерный data:URL + динамическая загрузка файлов стилей) позволяет добиться всех преимуществ технологии CSS Sprites, не затягивая загрузку страницы. При этом обладает очевидными плюсами: не нужно лепить все картинки в один файл, можно работать с каждой совершенно отдельно, что позволяет добиться большей семантичности кода и большего удобства использования сайтов. к тому же это несколько сократит CSS-код за счет уничтожения необходимости использовать background-position .

/ 26.01.2018

С ростом скорости интернет соединения и увеличении мощности не только десктопных, но и мобильных устройств веб страницы стают более «тяжелыми». Количество и размер подключаемых файлов растет: JavaScript файлы, css файлы, изображения, виджеты сторонних сайтов, iframe. На данный момент специфика работы браузеров такая, что при загрузке js файла блокируется отривсовка до того момента, пока скрипт не выполниться. Современные браузеры в фоновом режиме будут парсить документ и скачивать скрипты и стили, но отрисовка будет заблокирована. Сравнение сетевых параметров для различных браузеров можно посмотреть на browserscope.org. Мы не можем устранить блокировку полностью, но можем оптимизировать серверную и клиентскую часть приложения, что бы блокировка отрисовки занимала наименьший промежуток времени.

Решения для серверной части:
— Уменьшить размер передаваемых файлов
— Использовать CDN
— Вынести статические файлы на отдельный домен или под домен, таким образом увеличить количество одновременных соединений браузера.
— Включить сжатие передаваемых файлов(gzip)

Решения для клиентской части:
— Уменьшить количество запросов.
— Кэшировать файлы на стороне клиента с помощью заголовков Expires и Etags.
— Использовать общедоступные CDN(Google CDN, Yandex CDN). Таким образом, существует вероятность, что файл с общедоступного CDN уже будет храниться в кеше браузера.

Одним из способов оптимизации скорости загрузки сайта является асинхронная загрузка файлов, которая не блокирует отрисовку.

Скрипт асинхронной загрузки JavaScript:

(function() { var s = document.createElement(‘script’); s.type = ‘text/javascript’; s.async = true; s.src = ‘URL файла’; document.getElementsByTagName(‘head’).appendChild(script); })();

Если JavaScript нужно выполнить после загрузки всей страницы, включая содержание, изображения, стилевые файлы и внешние скрипты, то к загрузчику нужно добавить отслеживания события onload.

if (window.addEventListener) { window.addEventListener(‘load’, async_load, false); } else if (window.attachEvent) { window.attachEvent(‘onload’, async_load); }

Скрипт асинхронной загрузки JavaScript с учетом события onload

(function() { function async_load(){ var s = document.createElement(‘script’); s.type = ‘text/javascript’; s.async = true; s.src = ‘URL файла’; document.getElementsByTagName(‘head’).appendChild(script); } if (window.addEventListener) { window.addEventListener(‘load’, async_load, false); } else if (window.attachEvent) { window.attachEvent(‘onload’, async_load); } })();

Но это единичный случай, когда требуется загрузка одного файла. Часто на практике подключается множество файлов.

Скрипт асинхронной загрузки множества подключаемых JavaScript файлов

(function() { function async_load(){ [ ‘URL_файла_1.js’, ‘URL_файла_2.js’, ‘URL_файла_3.js’ ].forEach(function(src) { var s = document.createElement(‘script’); s.type = ‘text/javascript’; s.async = true; s.src = src; document.getElementsByTagName(‘head’).appendChild(script); }); } if (window.addEventListener) { window.addEventListener(‘load’, async_load, false); } else if (window.attachEvent) { window.attachEvent(‘onload’, async_load); } })();

Но в такой реализации есть минус — скрипты будут загружаться в произвольном порядке и соответсвенно выполнятся они будут произвольно во времени. Данный скрипт асинхронной загрузки идеально подходит, если выполнение JavaScript файлов не зависят один от другого и не зависит от DOM. В обратном случае его использование может привести к ошибкам на странице или непредвиденному результату выполнения. Для последовательного выполнения, но асинхронной загрузки, нужно указать async=false, тогда файлы будут скачиваться в произвольном порядке, но выполняться по очереди.

Стандарт HTML 5 поддерживает асинхронную загрузку JavaScript. Это можно сделать путем добавления ключевого слова async или defer. Например:

.jpg» type=»text/javascript» defer>

Скрипт, который подключен с атрибутом defer выполнится не нарушая порядок выполнения по отношению к остальным скриптам и его выполнение произойдет после полной загрузки и парсинга страницы, но перед тем, как вызовется DOMContentLoaded.

Скрипт, который подключен с атрибутом async выполнится при первой возможности после полной загрузки, но при этом не ожидает окончания парсинга документа и до загрузки объекта window. Браузеры не гарантируют выполнение скриптов в том же порядке в котором они подключены.

Библиотеки для асинхронной загрузки JavaScript

RequireJS — модуль загрузки JavaScript. Оптимизирован под браузеры, но он может использоваться в других средах, таких как Node, Rhino.

require([«script»], function(script) { console.log(«start after load script.js»); });

extsrc.js - библиотека, которая запускает скрипты на выполнение после того, как страница загрузится и отобразится пользователю. Работает корректно с document.write.

.jpg»>.jpg»>

yepnope.js — позволяет совершать асинхронную загрузку JavaScript и CSS файлов.

yepnope([ ‘script.js’, ‘style.css’ ]);

Простой способ загрузки JavaScript скриптов

Оказывается, что на практике добиться оптимальной кросс браузерной загрузки JavaScript скриптов, которые не блокируют отображение сложно, а порой невозможно..jpg»> в конец документа перед закрывающимся тегом body. Из за ограничения разных браузеров и самого HTML такой вариант загрузки, который не блокирует отображение, можно считать наиболее простой.

Google PageSpeed: CSS стили и JavaScript скрипты, блокирующие загрузку страницы на WP

В этом посту будет подразумеваться, что вы знакомы с инструментом Google по оптимизации скорости загрузки страниц сайта — PageSpeed Insights. Слушайте, да прямо сейчас вбейте туда свой сайт нажмите кнопку «Analize».

Окей, а теперь — о чём этот пост?

Вполне возможно, что в результатах проверки вашего сайта есть пункт «Eliminate render-blocking JavaScript and CSS in above-the-fold content».

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

Как его исправить в теории:

  • Объединяем все JavaScript файлы и размещаем то, что получилось перед закрывающим тегом сайта.
  • Объединяем все CSS, суём прямо перед JavaScript, которые мы уже переместили, затем выбираем из них те стили, которые необходимы для корректного отображения страницы, а в особенности её верхней части (первого экрана) и помещаем их в тег в сайта.
  • Как же обстоит дело на практике, и в данном конкретном случае — для сайтов на WordPress?

    1. Воспользуемся зависимостью других скриптов от jQuery

    В корректно состряпанной теме WordPress все CSS и JS файлы подключаются через wp_head() и wp_footer() — то есть в и в конце соответственно.

    Также у файлов есть зависимости, то есть например плагин должен подключаться после, а это значит, что если библиотека jQuery находится в wp_footer(), то FancyBox ну никак не может попасть в wp_head().

    Перемещаем jQuery в футер сайта

    Делается это очень просто — при помощи функций wp_deregister_script(), wp_register_script(), wp_enqueue_script() и хука (иногда используют хук в связке с is_admin()). Всё, что требуется от вас, это вставить код следующего содержания в файл вашего сайта.

    Хочу обратить ваше внимание на то, что это автоматизированное решение, и хотя оно работает практически в 100% случаев, бывает такое, что некоторые скрипты не хотят переноситься в футер сайта. Тогда уже потребуется более внимательный к каждому вашему файлу JavaScript.

    На этом наша работа с JS заканчивается, конечно прирост в скорости даст ещё и объединение скриптов (то есть снимаете их все с регистрации и потом просто подключаете свою объединенную версию) — но Google сейчас это уже не требует.

    2. Объединение CSS в WordPress

    Если объединение всех JavaScript в один файл — не всегда хорошая идея, то CSS-ки я бы рекомендовал объединять по возможности всегда.

    Помните скриншот в самом начале статьи (10 blocking CSS resources )? Откуда берется такое количество файлов стилей, ведь разработчик темы наверное понимал, что делает?

    Ответ — из плагинов.

    Например плагин «Contact Form 7» подключает свою собственную таблицу стилей, и хотя сама по себе она невелика, то лучше всё же избежать лишних HTTP-запросов.

    Давайте пошагово разберем как.

  • Копируете содержимое таблицы стилей плагина и вставляете его в конец основного файла стилей — .
  • Проверяете, проставлены ли в данных стилях относительные ссылки на изображения, например. Если да, то либо заменяете их на абсолютные, либо переносите изображения из плагина в папку с темой.
  • Заходите в настройки плагина и смотрите, есть ли возможность где-нибудь снять галочку и не подключать CSS плагина. В «Contact Form 7» такой возможности нет, а значит мы переходим к следующему пункту.
  • Отрубаем файлы через. Для стилей «Contact Form 7» код будет следующий:
  • Также иногда при помощи условных тегов файлы плагинов (как CSS, так и JS) отключают только с тех страниц, на которых они не используется.

    Ок, с «Contact Form 7» разобрались, а как узнать ID файлов CSS других плагинов?

    Да легко, открываем исходный код страницы и видим там подобную картину:

    Также есть плагин, который позволит выполнить объединение CSS и JavaScript автоматически — JS & CSS Script Optimizer.

    Если у вас остались вопросы, либо я забыл упомянуть о чем-либо в этой статье, пожалуйста, оставьте свой комментарий.

    Порядок загрузки страницы браузером

    Браузер загружает страницу последовательно. Особенно это актуально для внешних ссылках на файлы — css и javascript. Возьмем для примера блок для сайта lesnoy.name.

    Блог Лесного Владислава

    На данном сайте подгружается всего три внешних файла.

    2 из них — css стили, и один — js-файл. Но это пример простого сайта, зачастую подгружаются десятки внешних файлов и это существенно влияет на скорость загрузки страницы.

    Ускорение отображения страницы в браузере

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

    Т.е., из примера выше видно, что браузер загрузит заголовок сайта (title), затем встретит ссылку на внешний css файл main.css и пойдет загружать его. После загрузки он его обрабатывает и идет дальше — встречает второй css-файл, опять откладывает обработку страницы на потом и работает с prettify.css. Так же и с prettify.js. И лишь потом он принимается за отображения остальной страницы, уже применяя все обработанные ранее css-правила из css файлов и js-кол из javascript файлов.

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

    Можно, конечно. Самый банальный, но от этого не менее действенный метод — перенос всех не приоритетных внешних файлов с хедера сайта в футер. Т.е. с head-блока как можно ближе к тегу.

    Под не приоритетными файлами я подразумеваю те, которые не критичны для функциональности или внешнего вида сайта. Хороший способ разделить большой css или js файл на два — первый маленький хранит в себе то, что должно загрузиться как можно быстрее и размещается в head-секции, а второй и объемный содержит все остальное и располагается как можно ниже в html-коде страницы, не влияя на скорость отображения контента страницы.

    Но с приходом html5 можно сделать это проще и красивее. У тега script добавлен параметр async и defer .

    Атрибут async

    Атрибут тега script async делает загрузку js-файлов асинхронным. Те, кто умеют программировать на JS точно знают, как это — асинхронно. Тем же, кто не умеет — расскажу: браузер встречает ссылку на внешний javascript файл (тег script с параметром src), начинает выполнять его загрузку и обработку, но не останавливает при этом загрузку и обработку основной страницы.

    Т.е. делает это параллельно. Как раз то, что нам и нужно! И при этом не требуется переносить этот тег в футер (тем более не во всех CMS-системах это просто сделать).

    Недостаток атрибута async

    У асинхронной загрузки js-файла асинхронность является как плюсом так и минусом. Ведь размеры файлов скорее всего разные, скорость загрузки и обработки файлов так же не является детерминированной. А значит при асинхронной загрузки нескольких файлов нет никакой гарантии, что файл, который стал загружаться позже не загрузиться в итоге раньше (из-за размера в основном).

    В данном примере я не могу точно сказать, какая последовательность выполнения этих js-файлов будет. Я могу точно сказать лишь то, что script4 загрузиться после script3 из-за отсутствия у них атрибута async. Но какой файл из script1.js, script2.js и script5.js загрузиться раньше я не знаю, т.к. они загружаются асинхронно.

    Вставить/изменить ссылку

    «Да и какая нам разница?» — спросите вы. Но она появляется в том случае, если выполнения одного js-скрипта зависит от другого. Такое сейчас сплошь и рядом и самый простой пример такой зависимости — jQuery.

    В данном случае очень велика вероятность получения ошибки JavaScript из-за того, что какой-либо из jQuery плагинов начнет выполнятся раньше, чем загрузиться сам jQuery.

    Что же делать?

    Атрибут defer

    Тут нас и выручает другой атрибут script-тега — defer.

    Deferred переводиться с английского языка как «отложенный».

    Соответственно deferred javascript load — отложенная загрузка javascript. Если у ссылки на внешний js-файл браузер встречает атрибут defer, то он откладывает загрузку и выполнения этих файлов до тех пор, когда вся страница не будет загружена и отображена. При этом он гарантирует такой же порядок выполнения скриптов, который изначально и был установлен в html-коде.

    Соответственно, в нашем примере с jQuery и его плагинами defer нас выручает, выполняя две задачи: время отображения страницы существенно уменьшается (браузер не блокирует отрисовку страницы для загрузки js-файлов, он откладывает загрузку на потом) и при этом мы избавляется от возможных ошибках, связанных с асинхронной загрузкой зависимых друг от друга js файлов.

    В примере выше скрипт other_script.js загрузиться асинхронно, т.к. он не зависит от какого-либо другого файла, а jQuery и его плагины загрузятся сразу после отображения страницы в следующем порядке: сначала jquery.min.js, затем по порядку plugin1.jquery.js, plugin2.jquery.js, plugin3.jquery.js.

    В итоге с приходом html5 и атрибутов defer и async мы можем намного гибче управлять порядком загрузки внешних js-файлов, тем самым повышая скорость отрисовки веб-страницы . А, главное, для пользователя будет создаваться впечатления значительного повышения скорости загрузки всего веб-сайта в целом , ведь уже через несколько секунд он увидит то, зачем пришел на сайт — информацию.

    Доброго времени суток, уважаемые читатели Хабрахабра! Меня зовут Александр Шевченко, я начинающий веб-разработчик. Перейдём к делу. Анимации в CSS3 - давно не новинка. Однако, иногда можно сделать что-то простое эффектным. Сегодня мы по этому принципу создадим небольшую анимацию загрузки.

    Шаг 1. Плавное появление самого экрана загрузки

    Да-да. Перед тем, как приступить к основной части, мы сделаем анимацию появления самого экрана загрузки.

    Body { animation: body-opacity-change 1s ease-in-out 0s 1 forwards; opacity: 0; background-color: transparent; } @keyframes body-opacity-change { from { opacity: 0; background-color: transparent; } to { opacity: 1; background-color: #1b1c2c; } }
    Шаг 2. Основная часть экрана загрузки

    Теперь приступаем к самому экрану загрузки. Давайте сделаем основными компонентами анимации четыре отпрыгивающих шара.

    /* CSS */ div.circle { border-radius: 50%; background: #fff; width: 13px; height: 13px; display: inline-flex; align-items: center; justify-content: center; margin-top: 40%; }

    Шаг 3. Применяем стили к шарам

    Теперь начинается кульминация нашей небольшой работы. При помощи псевдоклассов:nth-child, :first-child и:last-child кастомизируем наши шары.
    Внимание! При создании анимации к каждому шару применяйте разную длительность самой анимации дабы шары подпрыгивали в разное время с разной скоростью.

    /* Первый шар */ div.circle:first-child { animation: upload 0.8s cubic-bezier(0.39, 0.56, 0.57, 1) 0s infinite alternate-reverse; background-color: #4285f4; margin-right: 6px; } /* Второй шар */ div.circle:nth-child(2) { animation: upload 1.3s cubic-bezier(0.39, 0.56, 0.57, 1) 0s infinite alternate-reverse; background-color: #34a853; margin-right: 3px; } /* Третий шар */ div.circle:nth-child(3) { animation: upload 1.1s cubic-bezier(0.39, 0.56, 0.57, 1) 0s infinite alternate-reverse; background-color: #fbbc05; margin-left: 3px; } /* Четвёртый шар */ div.circle:last-child { animation: upload 1.45s cubic-bezier(0.39, 0.56, 0.57, 1) 0s infinite alternate-reverse; background-color: #ea4335; margin-left: 6px; }
    Шаг 4. Создаём ключевые кадры анимации

    И таким образом, предпоследний шаг в нашем проекте - ключевые кадры анимации шаров.

    @keyframes upload { from { transform: translateY(35px); } to { transform: translateY(-35px); } }
    Шаг 5. Объединяем код

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

    Экран загрузки /* Тело страницы */ body { animation: body-opacity-change 1s ease-in-out 0s 1 forwards; opacity: 0; background-color: transparent; margin: 0; } /* Шары */ div.circle { border-radius: 50%; background: #fff; width: 13px; height: 13px; display: inline-flex; align-items: center; justify-content: center; margin-top: 40%; } /* 1-ый шар */ div.circle:first-child { animation: upload 0.8s cubic-bezier(0.39, 0.56, 0.57, 1) 0s infinite alternate-reverse; background-color: #4285f4; margin-right: 6px; } /* 2-ой шар */ div.circle:nth-child(2) { animation: upload 1.3s cubic-bezier(0.39, 0.56, 0.57, 1) 0s infinite alternate-reverse; background-color: #34a853; margin-right: 3px; } /* 3-ий шар */ div.circle:nth-child(3) { animation: upload 1.1s cubic-bezier(0.39, 0.56, 0.57, 1) 0s infinite alternate-reverse; background-color: #fbbc05; margin-left: 3px; } /* 4-ый шар */ div.circle:last-child { animation: upload 1.45s cubic-bezier(0.39, 0.56, 0.57, 1) 0s infinite alternate-reverse; background-color: #ea4335; margin-left: 6px; } /*--- Кейфреймы анимаций ---*/ /*-- Загрузка страницы --*/ @keyframes body-opacity-change { from { opacity: 0; background-color: transparent; } to { opacity: 1; background-color: #1b1c2c; } } /*-- Анимация шаров --*/ @keyframes upload { from { transform: translateY(35px); } to { transform: translateY(-35px); } }
    Демонстрация: код в песочнице SoloLearn
    Надеюсь, что это поможет Вам при создании Вашего веб-сайта. Это был самый простой пример экрана загрузки и поэтому я советую Вам не ограничивать свою фантазию. На этом желаю Вам удачи в вёрстке и прощаюсь.

    Я пытаюсь исключить 2 файла CSS, которые блокируют рендеринг на моем сайте, - они появляются в Google Page Speed ​​Insights. Я придерживался разных методов, ни один из которых не был успешным. Но недавно я нашел сообщение о Thinking Async и когда я применил этот код: он устранил проблему.

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

    4 ответов

    Уловкой запуска асинхронной загрузки стилей является использование элемента и установка недопустимого значения для атрибута media (я использую media = "none", но любое значение будет делать). Когда медиа-запрос оценивается как false, браузер все равно будет загружать таблицу стилей, но он не будет ждать, пока контент будет доступен до отображения страницы.

    После того, как таблица стилей закончила загрузку, атрибут media должен быть установлен на допустимое значение, поэтому правила стиля будут применены к документу. Событие onload используется для переключения свойства media на все:

    Этот метод загрузки CSS будет доставлять полезный контент посетителям намного быстрее, чем стандартный подход. Критический CSS все еще может быть использован с обычным блокирующим подходом (или вы можете встроить его для максимальной производительности), а некритические стили могут быть постепенно загружены и применены позже в процессе синтаксического анализа/рендеринга.

    Этот метод использует JavaScript, но вы можете обслуживать не-JavaScript-браузеры, обертывая эквивалентные блокирующие элементы в элементе :

    Вы можете увидеть операцию в www.itcha.edu.sv

    вы можете попробовать получить его несколькими способами:

    1. Использование media="bogus" и a на ноге

    2. Включение DOM по-старому

    (function(){ var bsa = document.createElement("script"); bsa.type = "text/javascript"; bsa.async = true; bsa.src = "https://s3.buysellads.com/ac/bsa.js"; (document.getElementsByTagName("head")||document.getElementsByTagName("body")).appendChild(bsa); })();

    3.если вы можете попробовать плагины, которые вы могли бы попробовать loadCSS

    // include loadCSS here... function loadCSS(href, before, media){ ... } // load a file loadCSS("path/to/mystylesheet.css");

    Будущее представляется preload keyword для link элементов.

    Версия синхронизации

    Версия Async

    К сожалению...

    Известные браузеры, которые еще не поддерживают эту функцию включают Edge и iOS Safari.

    Однако...

    loadCSS представляется потенциальным решением, которое позволяет вам использовать preload сегодня (с резервными копиями).



    Понравилась статья? Поделиться с друзьями: