5. DOMContentLoaded
- событие срабатывает при загрузке документа, кроме IE<9
- ждет css, если после него идет скрипт
- ждёт загрузки и выполнения скриптов (кроме скриптов с
async/defer, если есть поддержка и динамических)
- в FF/Chrome формы автозаполняются по
DOMContentLoaded
- интерфейсы обычно инициализируются по
DOMContentLoaded
7. Скрипты на странице*
Во время загрузки
Во время выполнения
- блокируется отрисовка страницы
- блокируют вообще все загрузки (IE<8, Opera<15)
- блокируют все загрузки, кроме стилей и скриптов
(IE8, FF, Chrome, Safari)
- остальные загрузки не блокируются (IE>8)
- ждет пока загрузятся предшествующие css файлы
- блокируют вообще всё
* - распространяется на скрипты со всех хостов
12. Скрипты в конце BODY
Chrome
- не блокируется рендеринг страницы
- не блокируются загрузки предыдущих ресурсов
- страница доступна до инициализации скриптов
18. script in iframe
- не блокирует рендеринг / загрузки
- необходимо вносить изменения в скрипты
- ограничение по домену
<iframe src='script.html' id="f1"></iframe>
<iframe src='script2.html' id="f2"></iframe>
19. script defer
- по стандарту только для внешних скриптов
- не блокирует рендеринг / загрузки
- выполнение после рендеринга страницы
- сохраняется порядок выполнения (кроме IE<10)
- IE4+, FF3.1+, Chrome 8+, Safari 5.1+, Opera 15+
<script src="jquery.js" defer></script>
<script src="scripts.js" defer></script>
20. script async
- по стандарту только для внешних скриптов
- не блокирует рендеринг / загрузки
- выполнение сразу после загрузки
- не сохраняется порядок выполнения
- IE10+, FF3.6+, Chrome 8+, Safari 5.1+, Opera 15+
<script src="script1.js" async></script>
<script src="script2.js" async></script>
21. XMLHttpRequest Eval
var xhr = getXmlHttp();
xhr.open("GET", "script.js", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
eval.call(window, xhr.responseText);
}
}
xhr.send(null);
- не блокирует рендеринг / загрузки
- не сохраняется порядок выполнения
- ограничение по домену
- нет индикации загрузки
22. XMLHttpRequest Injection
- не блокирует рендеринг / загрузки
- не сохраняется порядок выполнения
- ограничение по домену
- нет индикации загрузки
var xhr = getXmlHttp();
xhr.open("GET", "script.js", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var s=document.createElement('script');
document.getElementsByTagName('head')[0]
.appendChild(s);
s.text = xhr.responseText;
}
} xhr.send(null);
23. Script DOM
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = 'app.js';
document.getElementsByTagName('head')[0]
.appendChild(script);
- не блокирует рендеринг / загрузки
- не сохраняется порядок выполнения, кроме Opera<15
- async:true для Firefox 3.6, чтобы не сохранять порядок
- нет ограничений на домен
24. Script DOM + async:false
- не блокирует рендеринг / загрузки
- сохраняется порядок выполнения (кроме браузеров,
которые не поддерживают async, но не FF<3.6 и Opera)
- нет ограничений на домен
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = false;
script.src = 'app.js';
document.getElementsByTagName('head')[0]
.appendChild(script);
25. Script DOM + onreadystatechange
- не блокирует рендеринг / загрузки
- позволяет гибко управлять загрузкой / выполнением
- нет ограничений на домен
- только IE6+
var js = document.createElement('script');
js.onreadystatechange = function() {
if (js.readyState == 'loaded') {
document.body.appendChild(js); // execution
}
};
js.src = 'app.js';
26. Порядок загрузки не важен
Цель:
- Загрузить скрипты параллельно
- Выполнить сразу после загрузки
- Не блокировать рендеринг
- Не блокировать загрузку других ресурсов
- Кроссбраузерное решение
Решение: Script DOM
27. Порядок загрузки важен
Цель:
- Загрузить скрипты параллельно
- Выполнить последовательно
- Не блокировать рендеринг
- Не блокировать загрузку других ресурсов
- Кроссбраузерное решение
Решение: Script DOM + async:false / onreadystatechange
для IE / document.write для остальных браузеров
28. Техники связывания
- window onload
- timer
- script onload
- callback (m)
- degrading script tags (m)
m - требует модификации скриптов
30. window onload
if ( window.addEventListener ) {
window.addEventListener("load", init, false);
}
else if ( window.attachEvent ) {
window.attachEvent("onload", init);
}
- просто в реализации
- инициализация срабатывает слишком поздно
31. timer
function timer(interval) {
if ( typeof(jQuery) === "undefined" ) {
setTimeout(timer, interval);
}
else {
init();
}
}
timer(300);
- просто в реализации
- лишние расходы ресурсов на выполнение скрипта
- задержка при слишком большом интервале
32. script onload
js.onload = function() {
if ( !js.done ) {
js.done = true; init();
}
};
js.onreadystatechange = function() {
if ( !js.done &&
js.readyState.match(/loaded|complete/) ) {
js.done = true; init();
}
};
- выполнение инлайн скрипта максимально быстро
- немного сложнее в реализации
33. callback (m)
- выполнение инлайн скрипта максимально быстро
- вызов init() в конце app.js
- не гибкое решение
- требует модификации скриптов
function init() { ... }
var js = document.createElement('script');
js.src = "app.js"; document.getElementsByTagName('head')
[0].appendChild(js);
34. degrading script tags (m)
function init() { ... }
var js = document.createElement('script');
js.src = "app.js";
js.text = "init();"; document.getElementsByTagName('head')
[0].appendChild(js);
- гибкое решение
- требует модификации скриптов
inline script
<script type="text/javascript" src="app.js">
init();
</script>
35. degrading script tags (m)
var fs = document.getElementsByTagName("script");
var len = fs.length;
while ( len ) {
var s = fs[len-1];
if ( s.src.indexOf('app.js') != -1 ) {
eval( s.innerHTML );
break;
}
len--;
}
app.js
37. Загрузка виджетов
● Добавление через DOM
● Связывание через
onload/onreadystatechange
● document.write()
○ Делаем свой document.write()
○ Выносим виджет в отдельный
невидимый элемент
○ Загружаем в скрытый iframe,
по onload копируем на страницу
39. Преимущества подхода
Страница не виснет из-за сторонних виджетов
Управление виджетами из одного места
Гарантия подключения узла всего один раз (ID)