Отложить сценарии и порядок выполнения в браузерах

Я работал над добавлением атрибута defer для внешних скриптов, используемых в разделе HEAD одного из моих проектов. У меня был запрос на порядок выполнения нескольких отложенных тегов script.

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

Согласно http://www.w3.org/TR/html5/scripting-1.html

присутствует атрибут defer, тогда script выполняется, когда страница закончила синтаксический анализ

Атрибут defer работает. Но, я сомневаюсь в порядке исполнения. Похоже, что он отличается от FF и Chrome.

Как и в моем случае:

<script defer="defer" src="{SERVER_PATH}/deps.js?1441452359"></script>
<script defer="defer" src="{SERVER_PATH}/script1.js?1440067073"></script>
<script defer="defer" src="{SERVER_PATH}/script2.js?1441451916"></script>

Здесь deps.js представляет собой огромный файл размером около 120kb (gzipped), тогда как сценарий1-3 имеет обычный размер 20-50kb (gzipped).

В Firefox выполнение defer'ed script начинается в порядке появления, но не выполняется в том же порядке. Если на хром, если предыдущий script завершает выполнение, следующий запуск script не запускается. Похоже, Chrome имеет смысл.

Чтобы проверить порядок выполнения, я вставил console.log в первую и последнюю строку каждого сценария, например. в deps.js

console.log("Execution Start: deps");
// minified deps script content.
console.log("Execution End: deps");

Ниже консольного вывода в Firefox:

Execution Start: deps
Execution Start: script1
Execution Start: script2
// Script Error as script1 needs deps to render completely.
// Script Error as script2 needs deps to render completely.
Execution End: deps

Ниже консольного вывода в Chrome:

Execution Start: deps
Execution End: deps
Execution Start: script1
Execution End: script1
Execution Start: script2
Execution End: script2

Однако поведение на FF не всегда, как показано выше. Иногда это работает как Chrome. Это похоже на проблему, которая является только Firefox. Или, может быть, это из-за того, что файл deps.js является тяжелым и минимизированным и занимает время для рендеринга.

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

PS: Другие решения, такие как перемещение скриптов в нижней части страницы, не являются тем, что я рассматриваю в этот момент.

Ответ 1

Спецификация HTML5.0 говорит следующее:

Если элемент имеет атрибут src, а элемент имеет атрибут defer, и элемент помечен как "вставленный парсером", а элемент не имеет асинхронного атрибута

Элемент должен быть добавлен в конец списка сценариев, которые будут выполняться после завершения анализа документа, связанного с документом синтаксического анализатора, создавшего элемент.

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

Таким образом, он говорит, что откладывает выполнение скрипта до синтаксического анализа связанного Document, а также говорит, что он помещен в список. Таким образом, порядок списка должен быть таким, как порядок сценариев, который анализируется и вставляется.

Тем не менее, вторая часть волнует меня. В основном это говорит о том, что он будет помечен для выполнения только до тех пор, пока сетевая задача не закончит загрузку скрипта. Тогда... "парсер будет обрабатывать выполнение скрипта".

То, что я не смог найти в спецификации, это случай выполнения скрипта после разбора документа. Продолжает ли он выполнять сценарии в порядке списка, когда они становятся "готовыми к выполнению синтаксическим анализатором"? Или он подождет, пока все сценарии в списке не будут "готовы к выполнению парсера", а затем выполнит их.

Спецификация (шаг 15): http://www.w3.org/TR/html5/scripting-1.html#script-processing-src-prepare

Ответ 2

Я бы сказал, что это действительно не возможно, если журнал событий "Execution End" произошел в разных циклах событий, чем в журнале "Начало выполнения".

Можете ли вы обеспечить нас этим? В противном случае это будет означать, что Firefix здесь многопоточит, и, как мы знаем, в JS нет поддержки для этого.