Script Тег - async & defer

У меня есть пара вопросов об атрибутах async и defer для тега <script>, который, насколько я понимаю, работает только в браузерах HTML5.

Один из моих сайтов имеет два внешних файла JavaScript, которые в настоящее время находятся над тегом </body>; первый jquery, полученные из google и второй - локальный внешний script.

В отношении скорости загрузки сайта

  • Есть ли преимущества в добавлении async к двум сценариям, которые у меня есть в нижней части страницы?

  • Будет ли какое-либо преимущество в добавлении опции async к двум сценариям и помещению их в верхнюю часть страницы в <head>?

  • Это означает, что они загружаются при загрузке страницы?
  • Я предполагаю, что это вызовет задержки для браузеров HTML4, но ускорит ли загрузка страниц для браузеров HTML5?

Используя <script defer src=...

  • Загрузил бы два скрипта внутри <head> с атрибутом defer с тем же эффектом, что и скрипты перед </body>?
  • Вновь я предполагаю, что это замедлит браузер HTML4.

Используя <script async src=...

Если у меня есть два сценария с async включен

  • Будут ли они загружаться одновременно?
  • Или по одному с остальной частью страницы?
  • Значит ли порядок скриптов становится проблемой? Например, один script зависит от другого, поэтому если загрузка выполняется быстрее, вторая может выполняться неправильно и т.д.

Наконец, я лучше всего оставляю вещи так, как они есть до тех пор, пока HTML5 не будет использоваться чаще?

Ответ 1

Сохраните свои скрипты прямо перед </body>. Async можно использовать со сценариями, расположенными там в нескольких обстоятельствах (см. Обсуждение ниже). Defer не будет иметь большого значения для скриптов, расположенных там, потому что работа по разборке DOM в значительной степени уже была выполнена.

Вот статья, объясняющая разницу между асинхронными и отложенными: http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/.

Ваш HTML будет отображаться быстрее в старых браузерах, если вы сохраните скрипты в конце тела перед </body>. Таким образом, чтобы сохранить скорость загрузки в старых браузерах, вы не хотите размещать их где-нибудь еще.

Если ваш второй script зависит от первого script (например, ваш второй script использует jQuery, загруженный в первый script), то вы не можете сделать их async без дополнительного кода для управления порядком выполнения, но вы можете заставить их отложить, так как сценарии отсрочки будут выполняться по порядку, только после того, как документ будет проанализирован. Если у вас есть этот код, и вам не нужны сценарии для запуска сразу, вы можете сделать их асинхронными или отложенными.

Вы можете поместить скрипты в тег <head> и установить их в defer, а загрузка скриптов будет отложена до тех пор, пока DOM не будет проанализирован, и это ускорит отображение страниц в новых браузерах, которые поддерживают отсрочку, но это не поможет вам в старых браузерах, и на самом деле это не так быстро, как просто поставить скрипты прямо перед </body>, который работает во всех браузерах. Итак, вы можете понять, почему лучше всего поставить их перед </body>.

Async более полезен, когда вам действительно неинтересно, когда загружается script, и ничто другое, зависящее от пользователя, зависит от загрузки script. Наиболее часто цитируемый пример использования async - это аналитика script, как Google Analytics, которую вы не хотите ждать, и это не срочно для запуска в ближайшее время, и она стоит одна, поэтому от нее ничего не зависит.

Обычно библиотека jQuery не является хорошим кандидатом для async, потому что другие сценарии зависят от нее, и вы хотите установить обработчики событий, чтобы ваша страница могла начать отвечать на пользовательские события, и вам может потребоваться запустить некоторый код инициализации на основе jQuery, чтобы установить начальное состояние страницы. Его можно использовать async, но другие скрипты должны быть закодированы, чтобы не выполняться до загрузки jQuery.

Ответ 2

Это изображение объясняет обычный тег script, асинхронный и отложенный

введите описание изображения здесь

  • Асинхронные скрипты выполняются, как только загружается script, поэтому не гарантирует порядок выполнения (a script, который вы включили в конец может выполняться перед первым файлом script)

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

Ссылка: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html

Ответ 3

HTML5: async, defer

В HTML5 вы можете указать браузеру, когда запускаете свой код JavaScript. Существует 3 возможности:

<script       src="myscript.js"></script>

<script async src="myscript.js"></script>

<script defer src="myscript.js"></script>
  • Без async или defer браузер немедленно запустит ваш script, прежде чем отображать элементы, которые находятся ниже вашего тега script.

  • С async (асинхронным) браузер будет продолжать загружать HTML-страницу и отображать ее во время загрузки браузера и одновременно выполнять script.

  • При defer браузер запустит ваш script, когда страница закончит разбор. (не обязательно завершать загрузку всех файлов изображений. Это хорошо.)

Ответ 4

Оба сценария async и defer начинают загружаться сразу, не приостанавливая синтаксический анализатор, и оба поддерживают дополнительный обработчик onload для решения общей необходимости выполнять инициализацию, которая зависит от script.

Разница между async и defer начинается вокруг, когда выполняется script. Каждый async script выполняется при первой возможности после завершения загрузки и перед событием загрузки Windows. Это означает, что возможно (и, вероятно,), что сценарии async не выполняются в том порядке, в котором они происходят на странице. В то время как сценарии defer, с другой стороны, гарантированно выполняются в порядке их появления на странице. Это выполнение начинается после полного разбора парсинга, но перед событиями DOMContentLoaded документов.

Источник и дальнейшая информация: здесь.

Ответ 5

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

Асинхронный

При добавлении асинхронного атрибута к тэгу script произойдет следующее.

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  • Сделать параллельные запросы для извлечения файлов.
  • Продолжайте синтаксический анализ документа, как будто он никогда не прерывался.
  • Выполнять отдельные скрипты в момент загрузки файлов.

Перенести

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

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  • Сделать параллельные запросы для получения отдельных файлов.
  • Продолжайте синтаксический анализ документа, как будто он никогда не прерывался.
  • Закончить синтаксический анализ документа, даже если файлы script загружены.
  • Выполняйте каждый script в том порядке, в котором они встречались в документе.

Ссылка: Разница между Async и Defer

Ответ 6

Похоже, что поведение отсрочки и асинхронизации зависит от браузера, по крайней мере, на этапе выполнения. ПРИМЕЧАНИЕ. Отсрочка применяется только к внешним скриптам. Я предполагаю, что async следует тому же шаблону.

В IE 11 и ниже порядок выглядит следующим образом:

  • async (может частично выполняться при загрузке страницы)
  • none (может выполняться при загрузке страницы)
  • defer (выполняется после загрузки страницы, все откладываются в порядке размещения в файле)

В Edge, Webkit и т.д. атрибут async, кажется, либо игнорируется, либо помещается в конец:

  • data-pagespeed-no-defer (выполняется перед любыми другими скриптами, пока загружается страница)
  • none (может выполняться при загрузке страницы)
  • defer (ждет, пока DOM не загрузится, все отложите в порядке размещения в файле)
  • async (кажется, дождался загрузки DOM)

В новых браузерах атрибут data-pagespeed-no-defer выполняется перед любыми другими внешними скриптами. Это для сценариев, которые не зависят от DOM.

ПРИМЕЧАНИЕ. Используйте отсрочку, когда вам нужен явный порядок выполнения внешних скриптов. Это говорит браузеру выполнить все отложенные сценарии в порядке размещения в файле.

ASIDE: размер внешних javascripts имел значение при загрузке... но не влиял на порядок выполнения.

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

Ответ 7

Я думаю, что Джейк Арчибальд представил нам некоторые идеи еще в 2013 году, которые могут добавить еще больше позитива к теме:

https://www.html5rocks.com/en/tutorials/speed/script-loading/

У Святого Грааля есть набор скриптов, загружаемых немедленно, без блокировки рендеринга, и выполняются как можно скорее в порядке их добавления. К сожалению, HTML ненавидит вас и не позволит вам сделать это.

(...)

Ответ на самом деле в спецификации HTML5, хотя он скрыт внизу раздела загрузки скриптов. "Атрибут async IDL контролирует, будет ли элемент выполняться асинхронно или нет. Если установлен флаг" force-async "элемента, то при получении атрибут асинхронного IDL должен возвращать true, а при установке -" force-async " флаг должен быть сначала сброшен... ".

(...)

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

[
    '//other-domain.com/1.js',
    '2.js'
].forEach(function(src) {
    var script = document.createElement('script');
    script.src = src;
    script.async = false;
    document.head.appendChild(script);
});

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

Приведенный выше сценарий должен быть встроен в заголовок страниц, сценарий очередей загружается как можно быстрее, не прерывая прогрессивный рендеринг, и выполняется как можно скорее в указанном вами порядке. "2.js" можно загрузить до версии "1.js", но она не будет выполняться до тех пор, пока "1.js" не будет успешно загружен и выполнен или не выполнит одно из этих действий. Ура! асинхронная загрузка, но упорядоченное выполнение!

Тем не менее, это может быть не самый быстрый способ загрузки сценариев:

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

Мы можем добавить обнаруживаемость обратно, поместив это в заголовок документа:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

Это говорит браузеру, что странице нужны 1.js и 2.js. link [rel= subresource] похож на link [rel= prefetch], но с другой семантикой. К сожалению, в настоящее время он поддерживается только в Chrome, и вам нужно объявить, какие сценарии загружать дважды, один раз с помощью элементов ссылок и снова в своем сценарии.

Исправление: Изначально я сказал, что они были обнаружены сканером предварительной загрузки, а не нет, они были обнаружены обычным анализатором. Тем не менее, сканер с предварительной загрузкой может их подхватить, но пока нет, тогда как сценарии, включенные в исполняемый код, никогда не могут быть предварительно загружены. Спасибо Йоаву Вейссу, который исправил меня в комментариях.

Ответ 8

async и defer загрузят файл во время анализа HTML. Оба не будут прерывать парсер.

  • Сценарий с атрибутом async будет выполнен после его загрузки. Хотя сценарий с атрибутом defer будет выполнен после завершения анализа DOM.

  • Скрипты, загруженные с async, не гарантируют какой-либо порядок. В то время как скрипты, загруженные с атрибутом defer, поддерживают порядок их появления в DOM.

Используйте <script async>, когда скрипт не полагается ни на что. когда сценарий зависит от использования.

Лучшее решение было бы добавить в нижней части тела. С блокировкой или рендерингом проблем не будет.