Предисловие
Я считаю, что все столкнулись с множеством проблем, касающихся загрузки сценария JavaScript. В основном в нескольких точках -
1> Проблемы с загрузкой файла, зависимостью файла и заказа на выполнение, вызванные синхронными сценариями и асинхронными сценариями
2> Проблемы оптимизации производительности, вызванные синхронными сценариями и асинхронными сценариями
Глубокое понимание всех аспектов загрузки скрипта не только способствует решению практических проблем, но и способствует захвату и выполнению оптимизации производительности.
Сначала посмотрите на любой код тега сценария -
Кода -копия выглядит следующим образом:
<script src = "js/myapp.js"> </script>
Если он будет размещен на <Head>, он заблокирует все работы по рендерингу страницы, в результате чего пользователь останется в состоянии «белого экрана смерти» до тех пор, пока скрипт не будет загружен и выполнен. Сценарий в конце <body> позволит пользователю только увидеть статическую страницу без жизнеспособности. Где предполагается, что рендеринг клиента будет разбросан с неэффективными элементами управления и пустыми коробками. Соберите тестовый пример -
Кода -копия выглядит следующим образом:
<! Doctype html>
<html>
<head lang = "en">
<meta charset = "utf-8">
<Title> Async Загрузка Script </title>
<script src = "js/test.js"> </script>
</head>
<тело>
<div> Я доволен </div>
<img src = "img/test.jpg">
</body>
</html>
Среди них содержание в test.js -
Кода -копия выглядит следующим образом:
Alert («Я код сценария в голове. После выполнения JS здесь начинается рендеринг содержания тела!»);
Мы увидим, что оповещение - это точка паузы, и в настоящее время страница пустая. Тем не менее, имейте в виду, что вся страница была загружена в настоящее время. Если корпус содержит теги для определенных атрибутов SRC (например, метка IMG выше), браузер начал загружать соответствующий контент в настоящее время. Короче говоря, следует отметить, что рабочее время двигателя JS и двигателя рендеринга является взаимоисключающим (некоторые книги называют это потоком пользовательского интерфейса).
Поэтому нам нужно, чтобы сценарии отвечали за то, чтобы сделать страницу лучше выглядеть и использовать лучше, должны быть немедленно загружены, и сценарии, которые могут быть загружены позже, будут загружены позже.
1. Задержка выполнения скрипта
Теперь становится все более и более популярным размещать сценарии в конце страницы <Body>. Таким образом, с одной стороны, пользователь может видеть страницу быстрее, а с другой стороны, скрипт может непосредственно управлять элементами DOM, которые были загружены. Это «движение» является огромным улучшением для большинства сценариев. Модель страницы следующая -
Кода -копия выглядит следующим образом:
<! Doctype html>
<html>
<head lang = "en">
<!-метаданные и сценаристы идут сюда->
<script src = "headscript.js"> </script>
</head>
<тело>
<!-Контент идет здесь->
<script src = "bodyscript.js"> </script>
</body>
</html>
Это значительно ускоряет время рендеринга страницы, но имейте в виду, что это может дать пользователям возможность взаимодействовать со страницей до загрузки тела. Причина, по которой браузер не может загрузить сценарии перед загрузкой полного документа, является большое узкое место для больших документов, передаваемых по медленным соединениям.
В идеале, загрузка сценария должна выполняться одновременно с загрузкой документа и не влияет на рендеринг DOM. Таким образом, после того, как документ будет готов, сценарий можно запустить, потому что соответствующий сценарий был загружен в порядке тега <croppl>.
Мы можем выполнить это требование, используя DEFER, то есть
Кода -копия выглядит следующим образом:
<script src = "deferredscript.js"> </script>
Добавление атрибута Defer эквивалентно сообщению браузеру: пожалуйста, начните загружать этот скрипт немедленно, но, пожалуйста, подождите, пока документ не будет готов, и все сценарии с атрибутом Defer завершили запуск перед его запуском.
Таким образом, сценарии задержки в тег головы принесут все преимущества размещения сценариев на тег тела, и это может значительно улучшить скорость нагрузки больших документов. Режим страницы в это время -
Кода -копия выглядит следующим образом:
<! Doctype html>
<html>
<head lang = "en">
<!-метаданные и сценаристы идут сюда->
<script src = "headscript.js"> </script>
<script src = "deferredscript.js" defer> </script>
</head>
<тело>
<!-Контент идет здесь->
</body>
</html>
Тем не менее, не все браузеры поддерживают Defer (для некоторых современных браузеров, в случае объявления DEFE, их внутренние сценарии не будут выполнять документы. Это означает, что если вы хотите убедиться, что ваш скрипт задержки может работать после загрузки документа, вы должны инкапсулировать код всех сценариев задержки в структуру, такой как $ jQuery $ (Document) .Ready. Это того стоит, потому что почти 97% посетителей могут пользоваться преимуществами параллельной загрузки, в то время как еще 3% посетителей все еще могут использовать полнофункциональный JavaScript.
2. Полная параллелизация сценариев
Пусть сценарии будут загружены и выполнены на один шаг быстрее. Я не хочу ждать, пока сценарии отсрочки не заберут один за другим (DEFE напоминает нам о упорядоченном сценарии очереди, в котором документ тихо ждет загрузки документа), и я не хочу ждать, пока документ не будет готов до запуска этих сценариев. Я хочу загрузить и запустить эти сценарии как можно скорее. Здесь мы думаем об асинхровом атрибуте HTML5, но имейте в виду, что это хаотическая анархия.
Например, мы загружаем два совершенно нерелевантных сторонних сценария, и страница работает хорошо без них, и нам все равно, кто бежит первым, а кто работает позже. Следовательно, использование асинхрового атрибута на этих сторонних сценариях эквивалентно улучшению их скорости бега без потратить ни копейки.
Асинхронный атрибут вновь добавлен в HTML5. Функция аналогична DEFE, то есть она позволяет рендеринг DOM при загрузке сценариев. Тем не менее, он будет выполнен как можно скорее после загрузки (то есть двигатель JS простаивается и выполняется немедленно), и нет никакой гарантии, что сценарий будет выполнен по порядку. Они будут завершены до события Onload.
Firefox 3.6, Opera 10.5, IE 9, и последние Chrome и Safari поддерживают асинхронный атрибут. Async and Defer можно использовать одновременно, так что все IE после IE 4 поддерживают асинхронную нагрузку, но будьте осторожны, чтобы асинхронность перезаписывала отложение.
Тогда модель страницы в настоящее время выглядит следующим образом -
Кода -копия выглядит следующим образом:
<! Doctype html>
<html>
<head lang = "en">
<!-метаданные и сценаристы идут сюда->
<script src = "headscript.js"> </script>
<script src = "deferredscript.js" defer> </script>
</head>
<тело>
<!-Контент идет здесь->
<script src = "asyncscript1.js" Async Defer> </script>
<script src = "asyncscript2.js" Async Defer> </script>
</body>
</html>
Обратите внимание на заказ на выполнение здесь - каждый файл сценария загружается, затем выполняется Headscript.js, а затем Defferedscript.js загружается в фоновом режиме во время рендеринга DOM. Затем Defferedscript.js и два асинхронных сценария будут запускаться в конце рендеринга DOM. Обратите внимание, что для браузеров, которые поддерживают асинхронный атрибут, эти два сценария будут исчерпывать заказ.
3. Программируемая загрузка скрипта
Хотя функции вышеупомянутых свойств сценария очень привлекательны, они не широко используются из -за проблем совместимости. Поэтому мы используем сценарии, чтобы больше загружать другие сценарии. Например, мы хотим загрузить сценарий только для пользователей, которые соответствуют определенным условиям, что часто упоминается «ленивая загрузка».
На уровне API браузера есть два разумных способа ползания и запуска серверных сценариев -
1> Сгенерируйте запрос AJAX и используйте функцию Eval для обработки ответа
2> Вставьте тег <cript> в DOM
Последний метод лучше, потому что браузер будет беспокоиться о создании HTTP -запросов для нас. Кроме того, Eval также имеет некоторые практические проблемы: утечка, отладка - это грязная, а также может снизить производительность. Поэтому, если вы хотите загрузить скрипт с именем feature.js, мы должны использовать код, подобный следующему:
Кода -копия выглядит следующим образом:
var head = document.getElementsbytagname ('head') [0];
var script = document.createElement ('script');
script.src = 'feature.js';
Head.AppendChild (Script);
Конечно, нам нужно иметь дело с вызывным прослушиванием, а спецификация HTML5 определяет свойство Onload, которое может связывать обратные вызовы.
Кода -копия выглядит следующим образом:
script.onload = function () {
console.log ('сценарий загружен ...');
}
Тем не менее, IE8 и более старые версии не поддерживают нагрузку, они поддерживают OnreadyStateChange. Более того, есть еще много странных вещей, чтобы справиться с ошибками. Здесь вы можете ссылаться на некоторые популярные школьные библиотеки загрузки, такие как LabJ, yepnope, requirejs и т. Д.
Следующим образом, я сами инкапсулирую простой файл LoadJS -
Кода -копия выглядит следующим образом:
var loadjs = function (url, обратный вызов) {
var head = document.getElementsbytagname ('head') [0];
var script = document.createElement ('script');
script.src = url;
script.type = "text/javascript";
Head.AppendChild (Script);
// тег скрипта, в IE есть событие OneReadyStateChange, и есть событие Onload в соответствии с стандартом W3C
// IE9+ также поддерживает загрузку стандарта W3C
var ua = navigator.useragent,
ua_version;
// IE6/7/8
if (/msie ([^;]+)/. test (ua)) {
ua_version = parsefloat (regexp ["$ 1"], 10);
if (ua_version <= 8) {
script.onreadystatechange = function () {
if (this.readystate == "загружен") {
перезвонить();
}
}
} еще {
script.onload = function () {
перезвонить();
};
}
} еще {
script.onload = function () {
перезвонить();
};
}
};
Я не буду говорить об асинхронной загрузке сценариев в Document.Write. Теперь мало кто делает это, потому что различия в браузерах действительно ошеломляющие.
Обратите внимание, что использование объекта Image для предварительного загрузки JS -файлов асинхронно, код JS внутри не будет выполнен.
Наконец, давайте поговорим об асинхронном сценарии загрузки в redize.
requirejs не гарантирует, что целевые сценарии будут выполняться последовательно, а только гарантирует, что их порядок работы может соответствовать их соответствующим требованиям к зависимости. Поэтому мы гарантируем, что все сценарии загружаются параллельно как можно скорее и выполняем их упорядоченным образом в соответствии с топологией зависимости.
4. Резюме
Хорошо, когда дело доходит до этого, утверждение асинхронного сценария загрузки закончится. Позвольте мне снова поговорить о заказе оптимизации здесь -
1> традиционно, мы используем теги сценариев, чтобы непосредственно внедрить их в документы HTML. Вот две ситуации -
A> встроенный в тег головы - будьте осторожны, чтобы это не повлияло на параллельную загрузку других статических файлов ресурсов в содержимое документа. Это влияет на рендеринг содержимого документа, то есть рендеринг DOM в настоящее время будет заблокирован, и будет представлен белый экран.
В нижней части тега тела - чтобы избежать явления белого экрана, мы даем приоритет для рендеринга DOM, а затем выполнять сценарий, но проблема снова. Давайте сначала поговорим о первом вопросе - если содержание документа DOM является относительно большим, обязательство событий взаимодействия будет отложено, и этот опыт будет немного хуже. Конечно, нам нужно выполнить важные сценарии в первую очередь на основе потребностей. Давайте поговорим о второй проблеме - поскольку файлы скрипта находятся в доне тела, загрузка этих сценариев откладывается по сравнению со сценариями в голове. Следовательно, что касается нижней части тела, это не конечная точка оптимизации.
C> Добавить атрибут DEFE - мы надеемся, что сценарий будет загружен параллельно как можно скорее, и мы все равно будем вставить эту партию сценариев в голову. Загрузка сценария должна выполняться одновременно с загрузкой документа и не влияет на рендеринг DOM. Таким образом, сценарий можно запустить после готовности документа. Так что есть атрибут отсрочки. Но обратите внимание на его совместимость. Для браузеров, которые не поддерживают атрибут Defer, нам нужно инкапсулировать код в $ (документ). Разобедрен, например, jQuery. Следует отметить, что все сценарии с атрибутами отсрочки выполняются в последовательности в соответствии с их приказом появления, поэтому они также строго синхронизированы.
2> Предыдущий пункт касается синхронных сценариев выполнения (обратите внимание, что процесс загрузки этих сценариев параллелен, но разница между тем, кто сначала запускает запрос и кто затем вызывает запрос). Следующая точка оптимизации - «параллельные сценарии выполнения». Конечно, мы знаем, что в определенный момент времени выполняется только один файл JS. «Параллель» здесь означает, что тот, кто загружается в первую очередь, до тех пор, пока двигатель JS простаивает в настоящее время, он будет выполнен немедленно. Оптимизация здесь разделена на два типа -
a> Добавление асинхронного свойства - оно действительно может заполнить точку оптимизации, которую мы упомянули выше, но оно имеет высокие ограничения, то есть только для загрузки сценария беззависимости. Наиболее подходящий пример-ввести несколько сторонних сценариев. Кроме того, комбинация с атрибутом Deffer действительно имеет большое значение. Конечно, это также имеет проблемы с совместимостью. Вышеуказанные три проблемы привели к их нечастому применению. При использовании Async вы должны уделять пристальное внимание проблемам зависимости.
b> Сценарии сценария - очевидно, мы используем это для достижения цели «параллельного выполнения сценариев». В то же время мы также облегчаем контроль зависимостей сценария, поэтому мы используем интеллектуальное управление нагрузкой для асинхронной нагрузки в readyJ.
ОК, это все.
Здесь я просто говорю о контенте, связанном с асинхронными сценариями загрузки. Существует другая часть контента, которая представляет собой асинхронную загрузку файлов стиля или другие статические ресурсы. продолжение следует......