Pull to refresh

Comments 42

Еще интересен вариант сочетания http/2 и defer: загрузка скрипта и парсинг HTML — могут происходить одновременно, а запуск произойдет в момент, когда HTML будет готов, но раньше, чем это произошло бы при синхронном формировании запросов скриптов по ходу парсинга.

Когда парсер доходит до тега

Является ли блокирующим следующее объявление?

<script type="text/x-template" id="question">
    <div>
        content
    </div>
</script>


Где лучше размещать подобные блоки, в конце страницы или где угодно?

На сколько я понимаю — является. Если стоит задача использовать шаблоны, то я бы выбрал это

Тут нет ни загрузки сетевого ресурса, ни исполнения тяжелого кода, а потому вопрос является ли это объявление блокирующим — смысла не имеет.

Но парсер-то остановится, вопрос лишь в том, на долго ли (нет).

Нет. Парсер после полного чтения тэга сразу же пойдет дальше.


Эдак можно и обычный тэг <div> блокирующим объявить — ну а как же, парсер же останавливается чтобы его разобрать?

Старый я стал, не понимаю, зачем всё это? desktop.min.js и mobile.min.js — ответ на все вопросы, во всяком случае множество разных проблем заменяется на одну — юзеры с медленным соединением, для которых 2 мегабайта при каждом обновлении — это трудно. А уж если за 2 мега вылезли или обновления ежедневно — значит что то делаем не так.

Нет, это не вы старый, это пост устарел :-) Сейчас как раз склеивание всех скриптов в один файл с его минификацией куда более распространено, чем раньше. requirejs, systemjs, webpack — все они обходят рассмотренную тут проблему, делая ее не такой существенной.

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

Да, но при использовании современных инструментов экосистемы javascript выделение критических ресурсов делается совсем другими методами, имеющими мало общего с атрибутами async и defer.

Хм. Простой пример. Вот есть скрипт гугловый, который подключает карту. Вот есть мой некий common.js, в котором, скажем, описан какой-нибудь полифилл. Сайт встречает заголовком, текстом, формой, кучей текста, картинками и лишь в конце картой. Так вот как раз-таки для скрипта карты и пригодится defer. Гугл, кстати, так и рекомендует подключать у себя в примере.

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


От этого и стараются уйти, в том числе перечисленными мною инструментами.

Мы ускоряем отрисовку, а не ждём пока у нас загрузятся все ресурсы, которые, возможно, нам и не понадобятся. Чанки о том же, по-сути. Можно собрать всё в единый файл и пусть грузится или же разбить на части и грузить первыми только важные ресурсы, а остальные оставить на потом. Как минимум пользователь уже начнёт взаимодействовать с сайтом, а не будет ждать со словами «сайт тормозной». А, может, и вовсе уйдёт.

Суть одна — но механизмы-то разные! Вы понимаете, что выделение чанков в вебпаке совсем не похоже на простановку атрибутов async или defer скриптам?


Можно прочитать хоть сотню постов про атрибуты async и defer — но когда понадобится разбить пакет на чанки — придется лезть в документацию. И обратное тоже верно.

Не похоже. Мы разделили ресурсы, а затем сказали браузеру какой ресурс критичен, а какой нет.

Хотелось бы уточнить по поводу сохранения или не сохранения порядка выполнения нескольких скоиптов в случае с async и defer

Например, если есть большой внешний скрипт и небольшой инлайновый сразу после него, то можно ли сделать внешний скрипт deferred?
В общем случае стоит считать, что порядок выполнения скриптов не гарантируется ни для defer ни для async.
Если внешний JavaScript-файл размещается непосредственно перед закрывающим тегом body, то использование async и defer становится менее уместным

Менее уместно, но всё же уместно? Например, если у нас 5 внешних скриптов в конце body то без defer, они будут загружаться один за другим (так как парсер соответственно поочередно будет переходить от одного тэга script к другому). А вот с defer у каждого тэга можно загрузку распараллелить. Я правильно понимаю?

Смотрите какая штука.



Вот таким образом он забрал файлы.
А вот таким выполнил:


Уточните пожалуйста, из вашего примера, все 3 скрипта с defer атрибутом или без?

UFO just landed and posted this here

При этом в FF картина следующая:


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

При наличии атрибута defer порядок выполнения не определен. Кроме того, в defer скриптах нельзя выполнять document.write().
Скрипты без атрибута будут выполняться строго один за другим, как написано.


При открытом отладчике (или, особенно, Firebug’е) это на практике соблюдается не всегда.
Кантор пишет, что defer, в отличие от async, влияет на порядок выполнения — Асинхронные скрипты: defer/async
браузер гарантирует, что относительный порядок скриптов с defer будет сохранён.
На самом деле не так, в firefox и ie порядок исполнения может меняться — defer и firefox

Там описан серьезный баг, когда два скрипта начинают выполняться одновременно. Его давно починили.

Кантор пишет отличные статьи. Но давайте посмотрим как на самом деле. Вот что написано в стандарте:
If the element has a src attribute, and the element has a defer attribute, and the element has been flagged as «parser-inserted», and the element does not have an async attribute
The element must be added to the end of the list of scripts that will execute when the document has finished parsing associated with the Document of the parser that created the element.

The task that the networking task source places on the task queue once the fetching algorithm has completed must set the element's «ready to be parser-executed» flag. The parser will handle executing the script.

Тут сказано, что defer скрипты выполняются после парсинга документа, в по мере их загрузки. Кто загрузится первым, тот и выполнится. Только в IE<=9 порядок выполнения был предсказуем, но это поведение не соответствует стандарту и в следующих версиях его починили.

Не однозначно, сказано же, что скрипт добавляется в конец списка скриптов, который (список) будет исполнен после окончание парсинга документа. Сеть же загружает скрипты и помечает их как готовые к выполнению (а не передает на выполнение). В заблуждение вводит последняя фраза, так как не явно указано, или парсер сразу выполнит скрипт, или выполнит только когда дойдёт до него очередь. Но из параграфа выше всё же следует, что парсер выполняет скрипты поочерёдно, иначе бы спецификация явно не указывала бы, что скрипт нужно добавить в список, тем более вконец — в этом не было бы смысла. Ну и ребята из html5rocks о том же говорят.

Глядя на свежие Firefox 52 и Chrome 57, ваша трактовка похожа на правду.
С defer надо быть весьма осторожным, так как до тех пор пока не загрузятся скрипты с defer, не отработает событие domcontentloaded, а некоторые фреймворки, типа Angular, на это завязаны. И в случае если скрипт отдается очень долго, то и приложение все это время не будет работать.

если скрипт отдается очень долго, то ему ничего не поможет. даже если объявить его не defer, он все равно отодвинет domcontentloaded

UFO just landed and posted this here

Смело оставляйте как есть, без defer/async. Браузеры не парсинг html останавливают, а обработку html. То-есть они вполне знают какие скрипты следуют за актуальным и грузят их параллельно. И даже напротив, defer в хроме замедляет начало их загрузки, по видимому тратиться время на создание отдельного queue

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



Например, в V8 (используется в Chromium), сделана попытка разобрать все скрипты, независимо от их атрибутов, на отдельном выделенном потоке для выполнения скрипта. Таким образом, «блокирующая парсер» природа JavaScript-файлов должна быть минимизирована по умолчанию.

Блокировку можно уменьшить за счет устранения препарсинга.

Конечно же, блокировка есть. Любой скрипт может взаимодействовать с DOM и ожидает, что одновременно с его работой DOM меняться не будет. Поэтому парсер не имеет возможности достраивать DOM в процессе исполнения скрипта.


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


PS по приведенной вами ссылке этот вопрос воовсе не затрагивался

UFO just landed and posted this here
Sign up to leave a comment.

Articles