Говоря об отсрочке и асинхронности тега скрипта

внешний интерфейс

1. какого черта

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

    <script src="#link("xxxx/xx/home/home.js")" type="text/javascript" async defer></script>

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

2. Проведите исследование

Первый взглядasyncа такжеdeferДавайте определим свои собственные, откроем телескоп с красной сокровищницей, это введение

2.1 defer

Назначение этого свойства — указать, что скрипт не повлияет на построение страницы при выполнении. То есть сценарий задерживается до тех пор, пока вся страница не будет проанализирована перед запуском. Таким образом, в<script>набор элементовdeferсвойство, что эквивалентно указанию браузеру немедленно загрузить, но отложить выполнение.

Спецификация HTML5 требует, чтобы сценарии выполнялись в том порядке, в котором они появляются, поэтому первый отложенный сценарий выполняется до второго отложенного сценария, который, в свою очередь, выполняется доDOMContentLoadedисполнение события.в реальности, отложенные сценарии не обязательно будут выполняться по порядку и не будутDOMContentLoadВыполняется до того, как сработает время, поэтому лучше просто включить сценарий задержки.

2.2 async

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

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

В двух словах, эти два свойства вызывают асинхронную загрузку тега скрипта, но время выполнения отличается. ЦитироватьsegmentfaultКартинка из ответа вышеСиняя линия представляет чтение из сети, а красная линия представляет время выполнения, как для скриптов, так и для скриптов; зеленая линия представляет Разбор HTML.

то естьasyncвышел из строя, иdeferвыполняется последовательно, что также определяетasyncОн больше подходит для таких библиотек, как анализ Baidu или анализ Google, которые не зависят от других скриптов. Из рисунка видно, что общий<script>Загрузка и парсинг тегов синхронизированы, что блокирует отрисовку DOM, поэтому мы часто используем<script>написать на<body>Одной из причин внизу является предотвращение длинного белого экрана, вызванного загрузкой ресурсов, а другой причиной является то, что js может выполнять операции DOM, поэтому он должен выполняться после полной визуализации DOM.

2.3 точно?

Однако, эта картинка (чуть ли не единственный ответ, найденный Baidu) не является строгой, это просто нормативная ситуация, и большинство браузеров будут ее оптимизировать при реализации.

Посмотрим, как это сделает хром.

«Инсайдер технологии WebKit»:

  1. Когда пользователь вводит URL-адрес веб-страницы, WebKit вызывает свой загрузчик ресурсов для загрузки веб-страницы, соответствующей URL-адресу.

  2. Загрузчики полагаются на сетевые модули для установления соединений, отправки запросов и получения ответов.

  3. WebKit получает данные с различных веб-страниц или ресурсов, некоторые из которых могут быть получены синхронно или асинхронно.

  4. Веб-страница превращается интерпретатором HTML в серию слов (токен).

  5. Интерпретатор строит узлы из слов, формируя DOM-дерево.

  6. Если узел представляет собой код JavaScript, вызовите механизм JavaScript для его интерпретации и выполнения.

  7. Код JavaScript может изменить структуру дерева DOM.

  8. Если узел должен зависеть от других ресурсов, таких как изображения, CSS, видео и т. д., вызовите загрузчик ресурсов для их загрузки, но они асинхронны и не помешают продолжению создания текущего дерева DOM; если это URL-адрес ресурса JavaScript (без пометки асинхронного метода), создание текущего дерева DOM необходимо остановить, и создание дерева DOM не будет продолжаться до тех пор, пока ресурс JavaScript не будет загружен и выполнен движком JavaScript.

так, Вообще говоря, браузер Chrome сначала запрашивает HTML-документ, а затем вызывает соответствующий загрузчик ресурсов для выполнения асинхронных сетевых запросов для различных ресурсов в нем и одновременно выполняет рендеринг DOM, пока не встретит<script>Когда тег отображается, основной процесс останавливает рендеринг и ждет загрузки ресурса, затем вызывает движок V8 для анализа js, а затем продолжает анализ DOM. Мое понимание, если добавитьasyncАтрибуты эквивалентны открытию отдельного процесса для загрузки и выполнения независимо.deferда и будет<script>помещать<body>Тот же эффект внизу.

3. Поэкспериментируйте с одним выстрелом

3.1 demo

Для проверки сделанного выше вывода проверим

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.css" rel="stylesheet">
        <link href="http://cdn.staticfile.org/foundation/6.0.1/css/foundation.css" rel="stylesheet">
        <script src="http://lib.sinaapp.com/js/angular.js/angular-1.2.19/angular.js"></script>
        <script src="http://libs.baidu.com/backbone/0.9.2/backbone.js"></script>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
    </head>
    <body>
        ul>li{这是第$个节点}*1000
    </body>
    </html>

Простая демонстрация, 2 CSS3 JS ссылаются на разные CDN, а в теле создается 1000 li. Используйте временную шкалу Chrome для проверки, изменив расположение внешних справочных ресурсов и добавив соответствующие свойства.

3.2 Место в<head>Внутри


Асинхронно загружает ресурсы, но блокирует<body>При рендеринге появится белый экран, скрипт будет выполнен сразу по порядку

3.3 Место в<body>Нижний


асинхронно загружать ресурсы и т. д.<body>После завершения рендеринга содержимого и завершения загрузки JS выполняется по порядку.

3.3 Место в<head>голову и использоватьasync


Загружайте ресурсы асинхронно, и выполняйте ресурсы JS сразу после загрузки, не по порядку, кто быстрее, тот и пойдет первым

3.4 Место в<head>голову и использоватьdefer


Загружайте ресурсы асинхронно и последовательно выполняйте JS после рендеринга DOM.

3.5 Место в<head>голову и использовать обаasyncа такжеdefer


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

Подводить итоги, под движок webkit рекомендуемый способ все-таки поставить<script>написать на<body>Внизу вы можете использовать его, если вам нужно использовать независимые библиотеки, такие как Baidu Google Analytics или Buguanzi.asyncсвойства, если ваш<script>Этикетки должны быть написаны на<head>Можно использовать в головеdeferАтрибуты

4. Совместимость

Итак, попробуйте разобраться в психологии предшественников, и в чем причина написания при этом совместимости?

на Каниусе,asyncНе поддерживается, когда IEdeferПоддерживается в IEissueВ нем есть описание, а значит, в "телескопе" рекомендовано только одноdeferпричина. Таким образом, оба свойства указаны для того, чтобыasyncВключить, если не поддерживаетсяdefer,ноdeferВ некоторых случаях все еще есть ошибки.

The defer attribute may be specified even if the async attribute is specified, to cause legacy Web browsers that only support defer (and not async) to fall back to the defer behavior instead of the synchronous blocking behavior that is the default.

5. Вывод

На самом деле, самый безопасный способ<script>написать на<body>Внизу, никаких проблем с совместимостью, никаких проблем с белым экраном, никаких проблем с порядком выполнения, просто сядь и расслабься, ничего не делайdeferа такжеasyncцветок~

В настоящее время изучается только механизм рендеринга веб-кита Chrome. Необходимо дополнительно изучить Firefox и IE. Необходимо изучить рендеринг изображений, CSS и других внешних ресурсов.

Больше информации наздесь

Ссылаться на