Асинхронный JavaScript против отложенного. Включаем асинхронную загрузку JavaScript на WordPress

Большинство (если не все) современных сайтов используют Javascript. Кнопки социальных сетей? Плагины? Даже шаблоны! В 99% случаев эти компоненты будут использовать Javascript. Это означает, что на ваших сайтах используются скрипты. Но скрипты замедляют скорость работы сайта. Сегодня мы хотим представить вам 2 плагина, которые позаботятся об этой проблеме.

Асинхронное и отложенное… что?

Перед тем, как мы начнем, вам следует учитывать три вещи:

  • Parser – это HTML в стадии загрузки
  • Net – это время, за которое загружается ваш скрипт
  • Execution – это время, за которое скрипт полностью загружен для работы в браузере.
  • В рамках обычной среды работы сайта HTML парсинг приостанавливается на время выполнения скриптов. Если ваш сайт похож на мой, то это означает, что пользователь, перед тем, как сможет воспользоваться вашим сайтом, должен будет немного подождать (загрузки вашего кода, дизайна, контента и так далее). Давайте взглянем на то, как выглядит обычная загрузка скрипта:

    Отложенная загрузка просто позволяет вашему коду HTML загрузиться до того, как начнут выполять работу скрипты. Здесь преимущество заключается в том, что сайт мгновенно будет отображен в окне браузера, как бы демонстрируя молниеносную производительность. Лично я рекомендую использовать отложенную загрузку в тех случаях, если некоторые ваши пользователи используют браузеры, где отсутствует поддержка асинхронной загрузки скриптов. Давайте взглянем на то, как работает отложенная загрузка:

    Асинхронная загрузка скриптов – это лучшая опция. HTML-парсинг и загрузка скриптов будет продолжаться, но выполнение скриптов будет возможным только тогда, когда вся загрузка будет завершена. Это позволит вам максимально быстро представить контент сайта вниманию посетителей. Однако не все браузеры поддерживают асинхронную загрузку скриптов. Давайте взглянем на то, как происходит асинхронная загрузка:

    • Я, конечно же, рекомендую вам оптимизировать скрипты, используя оба метода.

    При использовании этих атрибутов, вам будут доступны 3 режима. Если вы используете атрибут async, то скрипт будет выполняться асинхронно, как только это станет возможным. Если вы не используете атрибут async, и вместо этого используете defer, то скрипт будет выполняться тогда, когда закончится парсинг страницы. Если вы не используете ни один из этих атрибутов, то скрипт будет загружаться и выполняться мгновенно, еще до того, как браузер начнет парсинг страницы.

    С чего начать?

    Итак, если Асинхронный javascript – это лучшая опция, позвольте представить вам лучший WordPress-плагин для асинхронной загрузки Javascript. Кто бы мог подумать, что называется он !

    Скачайте его, установите и – вы готовы к работе! Однако он будет конфликтовать с некоторыми плагинами, особенно если вы используете слайдеры. В настройках шаблонов WordPress зачасту присутствует такая функция. Вы можете исключить скрипты, которые должны загружаться мгновенно.

    Далее хочется перейти к отложенной загрузке Javascript. Я познакомился с плагинами, и мне показалось, что лучше всего работают плагины с точным соответствием названий. Лучшим в данной категории мне показался плагин под названием .

    Скачайте его, установите, и он начнет работу без каких-либо настроек, потому что в нем их просто-напросто нет. Он будет автоматически запускаться для тех пользователей, чьи браузеры не поддерживают асинхронную загрузку javascript. Я решил оставить этот пост максимально коротким, но при этом представил вам действительно самые лучшие плагины для оптимизации работы скриптов на ваших сайтах.

    Сейчас я расскажу Вам об интересном способе, который поможет вам ускорить свой сайт на WordPress за счет параллельной загрузки скриптов.

    Для чего это нужно?

    Все очень просто. Современный сайт представляет из себя сборник самых разнообразных скриптов, тегов, сниппетов, стилей, шрифтов и всего прочего. Как вы понимаете, чем больше «плюшек», тем дольше грузится ваш сайт. Что касается JavaScript, тут отдельная песня. Замечали ли вы такой косяк, когда страница вроде бы загрузилась, но вкладка показывает, что страница все еще грузится? Так бывает, когда какой-то отдельный скрипт не прогрузился до конца. Ладно бы так, иногда страница вообще простаивает до тех пор, пока не загрузится тот самый, вроде бы и не совсем важный скрипт. А у ваших пользователей просто может не хватить терпения.

    Данное понятие полностью противоположно синхронной загрузке, коей является обычный скрипт вида:

    Асинхронный вызов скрипта выглядит так:

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

    Как автоматизировать процесс?

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

    Находим уже знакомый нам файл functions.php вашей темы и вставляем туда (например в конец) следующий код:

    // асинхронный javascript function wcs_defer_javascripts ($url) { if (FALSE === strpos($url, ".js")) return $url; if (strpos($url, "jquery.js")) return $url; return "$url" async="async"; } add_filter("clean_url", "wcs_defer_javascripts", 11, 1);

    Заключение

    Что можно добавить в заключение. Данный скрипт, возможно, подойдет не всем, так-как, кто его знает, какие скрипты подключены именно у вас, поэтому, ставьте и экспериментируйте. Минуса у такого скрипта быть не может, разве что несовместимость с конкретным сайтом ввиду его специфики. Это был еще один маленький шаг по большой оптимизации вашего сайта.

    Эта проблема была предварительно затронута в статье: «Как JavaScript тормозит Веб (и что с этим делать)?»

    Для начала определимся с самой проблемой. Событие window.onload используется программистами для старта их веб-приложения. Это может быть что-то довольно простое, например, выпадающее меню, а может быть и совсем сложное, как пример, запуск почтового приложения. Суть проблемы заключается в том, что событие onload срабатывает только после того, как загрузится вся страница (включая все картинки и другое бинарное содержимое). Если на странице много картинок, то можно заметить некоторую задержку между загрузкой страницы и тем моментом, когда она начнет фактически работать. На самом деле, нам нужно только узнать способ определить, когда DOM полностью загрузится, а не ждать еще и загрузку картинок.

    Mozilla впереди планеты всей

    У Mozilla (прим.: на данный момент Firefox является более актуальным, поэтому далее упоминается именно он ) есть (недокументированное) событие специально для этих целей: DOMContentLoaded . Следующий образец кода выполняет как раз то, что нам нужно в Mozilla-подобных браузерах (а также в Opera 9):

    // для Firefox if (document.addEventListener) { document.addEventListener("DOMContentLoaded", init, false); } А Internet Explorer?

    IE поддерживает замечательный атрибут для тега <script> : defer . Присутствие этого атрибута указывает IE, что загрузку скрипта нужно отложить до тех пор, пока не загрузится DOM. Однако, это работает только для внешних скриптов. Следует также заметить, что этот атрибут нельзя выставлять, используя другой скрипт. Это означает, что нельзя создать с этим атрибутом, используя DOM-методы, — атрибут будет просто проигнорирован.

    Используя этот удобный атрибут, можно создать мини-скрипт, который и будет вызывать наш обработчик onload:

    Условные комментарии

    Есть некоторая проблема с этим подходом. Другие браузеры проигнорируют атрибут defer и загрузят этот скрипт сразу же. Существует несколько способов, как можно с этим побороться. Моим любимым методом является использование условных комментариев (conditional comments ), чтобы скрыть «отложенный» скрипт:

    IE также поддерживает условную компиляцию (conditional compilation ). Следующий код будет JavaScript-эквивалентом для заявленного выше HTML-кода:

    // для Internet Explorer /*@cc_on @*/ /*@if (@_win32) document.write(""); /*@end @*/ Все так просто?

    И конечно же, нам нужно обеспечить поддержку для остальных браузеров. У нас есть только один выход — стандартное событие window.onload:

    // для остальных браузеров window.onload = init; Двойное выполнение

    Остается одна маленькая неприятность (кто сказал, что будет легко?). Поскольку мы устанавливаем событие onload для всех (оставшихся) браузеров, то init сработает дважды в IE и Firefox. Чтобы это обойти, нам нужно сообщить функции, что она должна выполняться только один раз. Итак, наш метод init будет выглядеть примерно так:

    function init() { // выходим, если функция уже выполнялась if (arguments.callee.done) return; // устанавливаем флаг, чтобы функция не исполнялась дважды arguments.callee.done = true; // что-нибудь делаем };

    Прим.: лично мне кажется, что выставление глобальной переменной READY в данном случае более логично, ведь знать, что страница начала функционировать может потребовать не только одной функции init .

    Избавляемся от внешнего файла

    У описанного решения существует пара минусов:

    • Для IE нам требуется внешний JavaScript-файл
    • Не поддерживается Safari (Opera 9 поддерживает DOMContentLoaded)

    Большое спасибо Matthias Miller , теперь у нас есть решение и для Internet Explorer, которое не зависит от внешних файлов:

    // для Internet Explorer (используем условную компиляцию) /*@cc_on @*/ /*@if (@_win32) document.write(" "); var script = document.getElementById("__ie_onload"); script.onreadystatechange = function() { if (this.readyState == "complete") { init(); // вызываем обработчик для onload } }; /*@end @*/ И Safari тоже!

    Я позже почерпнул из листа рассылки jQuery , что, благодаря создателю jQuery, John Resig , существует решение и для Safari!

    if (/WebKit/i.test(navigator.userAgent)) { // условие для Safari var _timer = setInterval(function() { if (/loaded|complete/.test(document.readyState)) { clearInterval(_timer); init(); // вызываем обработчик для onload } }, 10); }

    По всей видимости, jQuery — это первая библиотека, которая имеет универсальное решение для заявленной проблемы.

    Полное решение // Dean Edwards/Matthias Miller/John Resig function init() { // выходим, если функция уже выполнялась if (arguments.callee.done) return; // устанавливаем флаг, чтобы функция не исполнялась дважды arguments.callee.done = true; // что-нибудь делаем }; /* для Mozilla/Firefox/Opera 9 */ if (document.addEventListener) { document.addEventListener("DOMContentLoaded", init, false); } /* для Internet Explorer */ /*@cc_on @*/ /*@if (@_win32) document.write(""); var script = document.getElementById("__ie_onload"); script.onreadystatechange = function() { if (this.readyState == "complete") { init(); // вызываем обработчик для onload } }; /*@end @*/ /* для Safari */ if (/WebKit/i.test(navigator.userAgent)) { // условие для Safari var _timer = setInterval(function() { if (/loaded|complete/.test(document.readyState)) { clearInterval(_timer); init(); // вызываем обработчик для onload } }, 10); } /* для остальных браузеров */ window.onload = init;

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

    Итак, приступим:

    Часто ваш HTML- или CSS-код может запрашивать какое либо изображение или файл. В том случае, если запрашиваемый объект не найден или не существует, скорость работы сайта существенно замедляется и увеличивается нагрузка на сервер, приводя к большому количеству неправильных запросов несуществующего объекта. И таких запросов намного больше, чем можно себе представить.

    Исправление ошибочных запросов гораздо проще нахождения их. Если вы нашли какой-либо неправильный запрос, просто уберите ненужный код из HTML- или CSS-файла или скорректируйте его.

    Крайне важно контролировать скорость загрузки страницы и отслеживать обращения к несуществующим ресурсам!

    Использование таких методов в CSS-файлах, как @import , может замедлять скорость загрузки стилей в частности и страниц в целом. Наибольшая сложность заключается в последовательной загрузке стилей (друг за другом) вместо использования возможности их параллельной (одновременной) загрузки. Это добавляет дополнительные шаги в процесс загрузки сайта.

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

    @import url("style.css")

    Заменить их необходимо на прямое подключение стилей в HTML-коде:

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

    Для этого сделайте простую операцию copy-paste из нескольких файлов в один! Один CSS-файл будет содержать ровно столько же полезной информации для сайта, но увеличит скорость загрузки!

    После объединения файлов не забудьте удалить лишние подключения старых файлов в HTML-коде страниц.

    Избегайте функции «document.write» в HTML

    Для того, чтобы вывести что-то на странице через JavaScript или для подключения внешнего ресурса, можно использовать функцию document.write , однако необходимо осознавать, что при использовании ее из HTML-кода для ее выполнения интернет-браузер будет осуществлять неоправданные операции загрузки-чтения-записи, негативно влияющие на скорость загрузки страниц сайта.

    Проверьте весь ваш HTML-код на наличие директив document.write , которые могут выглядеть так:

    document.write("");

    Вместо этого используйте просто подключение внешнего скрипта при помощи такого вызова в HTML-коде страницы:

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

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

    В качестве дополнительных мер можно использовать включение небольших скриптов в тело страниц и отложенную загрузку скриптов .

    На каждом сайте используется большое количество всевозможных изображений. И для отображения каждого из них веб-браузер передает по одному запросу, в ответ на которых сервер «отдает» соответствующее изображение.

    Количество обращений к серверу и, соответственно, скорость загрузки страниц можно уменьшить, объединяя несколько изображений в один CSS-спрайт (CSS-sprite). Вместо загрузки большого количества изображений ваш браузер теперь будет загружать одно! И в этом - прелесть CSS-спрайтов! Конечно, это в большей степени касается объединения нескольких небольших изображений, используемых в элементах оформления WEB-страницы (фоны меню, смайлы, углы, иконки и пр.).

    В этом случае для использования отдельно взятого элемента из состава CSS-спрайта потребуется вызов данного спрайта с последующим указанием размера и позиционированием необходимого элемента относительно общего размера CSS-спрайта.

    На примере двух изображений (рупора и смайла), объединенных в один спрайт, для отображения рупора напишем следующий CSS-стиль:

    Rupor {width:50px; height:50px; background:url(images/sprite.png) 0 0px;}

    Для смайла стиль будет выглядеть следующим образом:

    Smile {width:50px; height:50px; background:url(images/sprite.png) 0 –50px;}

    Соответствующие им фрагменты HTML-кода будут такими:

    Для рупора:

    И для смайла:

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

    Только обозначенное ниже решение позволит загружать внешний скрипт ТОЛЬКО после полной загрузки страницы и не вызовет предупреждение «Defer loading of javascript» в инструментах для веб-мастеров от Google. Вот он, рекомендуемый Google, метод:


    function downloadJSAtOnload() {
    var element = document.createElement("script");
    element.src = "script.js ";
    document.body.appendChild(element);
    }
    if (window.addEventListener)
    window.addEventListener("load", downloadJSAtOnload, false);
    else if (window.attachEvent)
    window.attachEvent("onload", downloadJSAtOnload);
    else window.onload = downloadJSAtOnload;