Что означают defer
и async
?
По умолчанию тег <script src=...></script>
является злым! Браузер должен прекратить анализ HTML до тех пор, пока скрипт не будет загружен и выполнен (поскольку скрипт может вызывать document.write(...)
или определять глобальные переменные, которые будут позже скриптами зависит от). Это означает, что любые изображения и таблицы стилей, которые находятся после тега скрипта, не начинают загрузку до тех пор, пока скрипт не завершит загрузку и выполнение. Внешние сценарии обычно заставляют Интернет загружаться намного медленнее, поэтому NoScript стал таким популярным.
Microsoft представила defer
для решения проблемы. Если вы используете <script defer src=...></script>
, вы обещаете не звонить document.write(...)
. Внешний скрипт defer
начнет загружаться немедленно, но не будет выполняться до тех пор, пока страница не будет отображена. После отображения страницы все сценарии defer
выполняются в том же порядке, в котором они были объявлены. Не все браузеры поддерживают defer
.
В HTML5 введен атрибут async
, который может выполняться в любое время - возможно, до завершения анализа страницы или даже до других сценариев defer
/ async
, которые все еще загружаются. Но сложнее использовать несколько async
скриптов, потому что порядок их выполнения не гарантирован. Как и defer
, не все браузеры поддерживают async
.
После того, как все сценарии defer
и async
выполнены, события DOMContentLoaded
и load
запускаются.
Краткая история defer
и async
- 1997 IE 4 представляет
defer
.
- 1998 Спецификация HTML 4 упоминает
defer
, но, к сожалению, точно не говорится, когда выполняются defer
сценарии (Все по порядку? До onload
?). Таким образом, ни один другой браузер не реализует defer
, потому что никто не хочет перепроектировать поведение IE или нарушать скрипты, которые могут зависеть от особенностей IE. (См., Например, запрос функции Mozilla ).
- 2006 Черновик HTML5 наконец описывает детали, необходимые для реализации
defer
: defer
все сценарии должны выполняться по порядку после анализа остальной части страницы и до onload
. Также вводится async
для указания сценариев, которые могут выполняться всякий раз, когда они загружаются, без необходимости ждать друг друга. К сожалению, HTML5 противоречит IE, так как не допускает встроенные defer
скрипты. Это нарушает инвариант , что все defer
сценарии выполняются по порядку (если некоторые defer
сценарии имеют src
, а некоторые имеют встроенное содержимое).
- 2009 Gecko 1.9.1 (Firefox 3.5) поддерживает
defer
.
- 2010-01 Gecko 1.9.2 (Firefox 3.6) поддерживает
async
.
- 2010-09
defer
и async
проверены в Webkit . Вы должны увидеть это в Chrome и Safari очень скоро (он уже находится на канале разработчика Chrome, но он немного глючит).
- Мы все еще ждем, пока Opera реализует
defer
и async
, а IE пока реализует async
.
Так, что должен использовать веб-разработчик?
В настоящее время нет единого правила для подражания. Вы должны выбрать решение, которое наилучшим образом сочетает в себе простоту, задержку отображения страницы и задержку выполнения скрипта для набора браузеров, которые обращаются к вашему сайту.
- Самый простой способ отрисовки страницы перед выполнением сценариев, как указывали другие, - это поместить ваши сценарии внизу страницы. Но если сценарии необходимы, или веб-страница содержит много HTML-кода, вы должны разместить свои сценарии выше на странице.
- Если ваш скрипт автономен и ваши клиенты используют IE или новые версии Firefox, используйте
<script async defer src=...></script>
: это позволяет продолжать рендеринг параллельно загрузке скриптов для IE и новейших браузеров HTML5, но вызывает браузеры до HTML5 (включая все версии оперы) заблокировать. - Если один внешний скрипт зависит от другого, отметьте их оба
defer
(но не async
), и они будут выполнены в том порядке, в котором они были объявлены (за исключением IE <= 9, при определенных условиях может выполнятьсяони вышли из строя </a>).Опять же, это позволяет продолжать рендеринг параллельно загрузке скриптов в IE и Gecko / Webkit с поддержкой HTML5, но пострадают более старые браузеры и Opera.Рекомендуется использовать defer
, даже если сценарии находятся внизу страницы, чтобы они загружались параллельно друг другу. - Никогда не используйте
defer
для встроенных сценариев, поскольку черновой вариант HTML5Откажитесь от гарантии выполнения. - Если в вашей аудитории много пользователей Opera или старых пользователей Firefox / Safari, следующий фрагмент кода выполнит сценарий после анализа документа в большинстве браузеров до HTML5 (IE, Webkit, необходимо протестироватьстарый Firefox), хотя новейшие браузеры, поддерживающие HTML5, начинают загрузку немедленно, но не блокируют выполнение скрипта из-за атрибута
async
.Другими словами, большинство старых браузеров обрабатывают его как скрипт внизу страницы, а новейшие браузеры распознают async
.Но пользователи Opera получают худшее из обоих миров, потому что Opera немедленно начинает выполнение и не понимает async
.Это шаблон , рекомендуемый Google Analytics для ежа на многих веб-страницах.
фрагмент:
<script>
(function() {
var script = document.createElement('script');
script.src = '...';
script.async = true;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(script, s);
})();
</script>
- Если другой сценарий зависит отзагрузите первый сценарий, затем вы можете использовать тот же шаблон, что и выше, но прослушать событие onload первого элемента сценария перед выполнением второго сценария.См. Пример LABjs, чтобы узнать, как ждать загрузки другого сценария .
- Если у вас несколько сценариев со сложными зависимостями, используйте LAB.js или YUI Loader , чтобы они загружались параллельно и выполнялись в каком-то действительном порядке.
- Если вы используете популярную библиотеку, такую как jQuery, рассмотрите возможность использования копии Google вместо своей собственнойчтобы повысить вероятность того, что браузер уже кеширует его.
Обновление : если у вас есть сценарии, разбитые на модули, и вы хотите повысить производительность, я рекомендую «Объединение асинхронных сценариев»глава даже более быстрых веб-сайтов Стивом Соудером.Он содержит советы и рекомендации не только для контроля порядка выполнения, но также и для задержки анализа сценариев для повышения производительности.