На веб-странице есть много мест, которые можно оптимизировать для повышения производительности.Одним из наиболее распространенных способов является асинхронная загрузка файлов скриптов js. Прежде чем говорить об асинхронной загрузке, давайте посмотрим, как браузер загружает js-файлы.
Браузер загружает скрипт JavaScript, в основном через
<script>
Элемент завершен. Обычный процесс загрузки страницы выглядит так.
- Браузер начинает синтаксический анализ HTML-страницы по мере ее загрузки. То есть он не ждет, пока загрузка завершится, а затем начинает синтаксический анализ.
- В процессе парсинга браузер находит
<script>
элемент, приостановить синтаксический анализ и передать управление рендерингом веб-страницы движку JavaScript.- если
<script>
Если элемент ссылается на внешний скрипт, загрузите скрипт и выполните его, в противном случае выполните код напрямую.- После выполнения механизма JavaScript управление возвращается механизму рендеринга, чтобы возобновить синтаксический анализ HTML-страниц.
При загрузке внешнего скрипта браузер приостановит отрисовку страницы, дождется загрузки и выполнения скрипта, а затем продолжит отрисовку. Причина в том, что код JavaScript может модифицировать DOM, поэтому управление должно быть передано ему, иначе это приведет к сложным проблемам гонки потоков.
Вышеупомянутое — это то, что мы обычно видим чаще всего.<script>
этикетка на<head>
На практике такой способ загрузки называетсясинхронная загрузка, или блокируя загрузку, потому что при загрузке файла скрипта js браузеру будет заблокирован анализ HTML-документа, и HTML-документ не будет проанализирован до завершения загрузки и выполнения. Если время загрузки слишком велико (например, время загрузки слишком велико), это приведет к тому, что браузер «симулирует смерть», и страница будет пустой. Более того, положить<head>
DOM нельзя манипулировать в файле js, загруженном синхронно в , иначе возникнет ошибка, потому что в это время HTML не проанализирован и DOM не сгенерирован. С этой точки зрения опыт синхронной загрузки часто не очень хорош.
Давайте рассмотрим несколько способов асинхронной загрузки.
-
Буду
<script>
этикетка на<body>
НижнийСтрого говоря, это не асинхронная загрузка, но это также распространенный способ улучшить производительность страницы, изменив способ загрузки js, поэтому я разместил его здесь.
Буду
<script>
помещать<body>
По сути, это решает несколько проблем, упомянутых выше.Во-первых, это не приведет к блокировке парсинга страницы.Даже если время загрузки слишком велико, пользователи могут видеть страницу, а не пустую, и в это время DOM может манипулировать в сценарии. -
defer
АтрибутыДавая
<script>
Настройки ярлыкаdefer
свойство для установки файла скрипта на ленивую загрузку, когда браузер встречаетdefer
атрибут<script>
тег, он откроет другой поток для загрузки файла js и одновременно продолжит анализ документа HTML.После того, как весь HTML будет проанализирован и DOM загружен, загруженный файл js будет выполнен.Этот метод подходит только для ссылок на внешние файлы js.
<script>
тег, вы можете убедиться, что порядок выполнения нескольких файлов js совпадает с порядком их появления на странице, но обратите внимание на добавлениеdefer
файлы JS для свойств не должны использовать метод document.write. -
async
Атрибутыasync
свойства иdefer
Свойства аналогичны, и будет открыт поток для загрузки файла js, но такой же, какdefer
Иными словами, он будет выполняться сразу после завершения загрузки, а не ждать, пока загрузится DOM, поэтому он все равно может вызвать блокировку.такой же,
async
Он также применим только к внешним файлам js, а метод document.write нельзя использовать в js, но для нескольких файлов сasync
js, нельзя гарантировать, что он будет выполнен в том же порядке, что и defer, какой бы js-файл был загружен первым, он будет выполнен первым. -
динамически созданный
<script>
Этикеткаможет быть создан динамически с помощью
<script>
тег для асинхронной загрузки js-файлов, например следующий код:(function(){ var scriptEle = document.createElement("script"); scriptEle.type = "text/javasctipt"; scriptEle.async = true; scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js"; var x = document.getElementsByTagName("head")[0]; x.insertBefore(scriptEle, x.firstChild); })();
или
(function(){ if(window.attachEvent){ window.attachEvent("load", asyncLoad); }else{ window.addEventListener("load", asyncLoad); } var asyncLoad = function(){ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); } })();
Среди двух вышеперечисленных методов первый метод предотвратит срабатывание события onload до его выполнения, а теперь код многих страниц выполняет дополнительную работу по отрисовке во время загрузки, поэтому обработка инициализации некоторых страниц все равно будет заблокирована. Второй не предотвратит срабатывание события onload.
Вот краткое описание
window.DOMContentLoaded
а такжеwindow.onload
Разница между этими двумя событиями заключается в том, что первое запускается после анализа DOM.При анализе DOM JavaScript может получить ссылку на DOM, но некоторые ресурсы на странице, такие как изображения, видео и т. д., не были обработаны. загружается, а функция такая же, как и в событии jQuery.ready. Последнее — когда страница загружена полностью, включая различные ресурсы.
После разговора об этих распространенных способах асинхронной загрузки js-скриптов, давайте рассмотрим последний вопрос, когда его использовать.defer
, когда использоватьasync
Шерстяная ткань? Вообще говоря, выбор между ними зависит от того, есть ли зависимость между сценариями, Если есть зависимость, порядок выполнения должен быть гарантирован.defer
Использовать без зависимостейasync
, если использовать одновременноdefer
неверный. Обратите внимание, что ни один из них не должен использовать document.write, это приведет к очистке всей страницы.
На следующем рисунке показана синхронная загрузка иdefer
,async
Разница при загрузке, где зеленая линия представляет синтаксический анализ HTML, синяя линия представляет чтение js-скрипта по сети, а красная линия представляет время выполнения js-скрипта: