non-blocking java script

3,566

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,566
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
12
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

non-blocking java script

  1. 1. Non-Blocking JavaScript Dmitriy Yakubovskiy
  2. 2. Параллельные загрузки
  3. 3. Потоки по браузерам * Firefox 3+ 6 потоков Chrome 6 потоков Safari 3-4 4 потока Safari 5 6 потоков Opera 12 6 потоков IE 6-7 2 потока IE 8-9 6 потоков IE 10 8 потоков * - число параллельных соединений к одному хосту
  4. 4. Процесс отрисовки Исходный HTML DOM дерево Дерево отрисовки
  5. 5. DOMContentLoaded - событие срабатывает при загрузке документа, кроме IE<9 - ждет css, если после него идет скрипт - ждёт загрузки и выполнения скриптов (кроме скриптов с async/defer, если есть поддержка и динамических) - в FF/Chrome формы автозаполняются по DOMContentLoaded - интерфейсы обычно инициализируются по DOMContentLoaded
  6. 6. DOMContentLoaded (Firefox)
  7. 7. Скрипты на странице* Во время загрузки Во время выполнения - блокируется отрисовка страницы - блокируют вообще все загрузки (IE<8, Opera<15) - блокируют все загрузки, кроме стилей и скриптов (IE8, FF, Chrome, Safari) - остальные загрузки не блокируются (IE>8) - ждет пока загрузятся предшествующие css файлы - блокируют вообще всё * - распространяется на скрипты со всех хостов
  8. 8. Скрипты в HEAD IE6-7
  9. 9. Скрипты в HEAD IE8
  10. 10. Скрипты в HEAD IE9
  11. 11. Скрипты в HEAD Сhrome / Safari / FF
  12. 12. Скрипты в конце BODY Chrome - не блокируется рендеринг страницы - не блокируются загрузки предыдущих ресурсов - страница доступна до инициализации скриптов
  13. 13. Заглушки интерфейсов
  14. 14. <link rel="stylesheet" type="text/css" href="styles.css" /> <!--[if lte IE 8]> <link rel="stylesheet" type="text/css" href="ie.css"> <![endif]--> Conditional Comments (IE)
  15. 15. Conditional Comments (IE) <!--[if IE]><![endif]--> <link rel="stylesheet" type="text/css" href="styles.css" /> <!--[if lte IE 8]> <link rel="stylesheet" type="text/css" href="ie.css"> <![endif]-->
  16. 16. Не блокирующие скрипты - document.write - script in iframe - script defer - script async - XMLHttpRequest Eval - XMLHttpRequest Injection - Script DOM
  17. 17. document.write IE6 document.write('<scr'+'ipt src="jquery.js"></scr'+'ipt>'); document.write('<scr'+'ipt src="scripts.js"></scr'+'ipt>'); - не блокирует другие скрипты - сохраняет порядок выполнения - блокирует рендеринг, загрузку css/img - актуально только для IE<8, Opera<15
  18. 18. script in iframe - не блокирует рендеринг / загрузки - необходимо вносить изменения в скрипты - ограничение по домену <iframe src='script.html' id="f1"></iframe> <iframe src='script2.html' id="f2"></iframe>
  19. 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. 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. 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. 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. 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. 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. 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. 26. Порядок загрузки не важен Цель: - Загрузить скрипты параллельно - Выполнить сразу после загрузки - Не блокировать рендеринг - Не блокировать загрузку других ресурсов - Кроссбраузерное решение Решение: Script DOM
  27. 27. Порядок загрузки важен Цель: - Загрузить скрипты параллельно - Выполнить последовательно - Не блокировать рендеринг - Не блокировать загрузку других ресурсов - Кроссбраузерное решение Решение: Script DOM + async:false / onreadystatechange для IE / document.write для остальных браузеров
  28. 28. Техники связывания - window onload - timer - script onload - callback (m) - degrading script tags (m) m - требует модификации скриптов
  29. 29. Техники связывания <script type="text/javascript"> function init() { ... App.start(); ... } init(); </script> <script type="text/javascript" src="app.js"></script>
  30. 30. window onload if ( window.addEventListener ) { window.addEventListener("load", init, false); } else if ( window.attachEvent ) { window.attachEvent("onload", init); } - просто в реализации - инициализация срабатывает слишком поздно
  31. 31. timer function timer(interval) { if ( typeof(jQuery) === "undefined" ) { setTimeout(timer, interval); } else { init(); } } timer(300); - просто в реализации - лишние расходы ресурсов на выполнение скрипта - задержка при слишком большом интервале
  32. 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. 33. callback (m) - выполнение инлайн скрипта максимально быстро - вызов init() в конце app.js - не гибкое решение - требует модификации скриптов function init() { ... } var js = document.createElement('script'); js.src = "app.js"; document.getElementsByTagName('head') [0].appendChild(js);
  34. 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. 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
  36. 36. Загрузчики - $script.js - YepNope.js - Control.js - LAB.js - Head.js - Load.js - Require.js Как будем загружать сам загрузчик?
  37. 37. Загрузка виджетов ● Добавление через DOM ● Связывание через onload/onreadystatechange ● document.write() ○ Делаем свой document.write() ○ Выносим виджет в отдельный невидимый элемент ○ Загружаем в скрытый iframe, по onload копируем на страницу
  38. 38. Загрузка виджетов (function(d, s) { var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) { if (d.getElementById(id)) {return;} js = d.createElement(s); js.src = url; js.id = id; fjs.parentNode.insertBefore(js, fjs); }; load('widget1.js', 'fbjssdk'); load('widget2.js', 'gplus1js'); load('widget3.js', 'tweetjs'); }(document, 'script'));
  39. 39. Преимущества подхода Страница не виснет из-за сторонних виджетов Управление виджетами из одного места Гарантия подключения узла всего один раз (ID)
  40. 40. Постзагрузка виджетов
  41. 41. Постзагрузка виджетов
  42. 42. Полезные материалы Ресурсы www.browserscope.org www.stevesouders.com Книга Steve Souders - Even Faster Web Sites Таблица сравнения загрузчиков https://spreadsheets.google.com/a/sysiq.com/lv? key=tDdcrv9wNQRCNCRCflWxhYQ
  43. 43. ● WebPageTest Online (www.webpagetest.org) ● Webkit Developer Toolbar (Timeline Tab) ● Firebug for FF (YSlow add-on, Net Tab) ● Fiddler (Web Debugging Proxy) ● DynaTrace Ajax Edition ● Sloppy (proxy server) Инструменты
  44. 44. Вопросы? Задавайте умные вопросы. Получайте умные ответы.
  45. 45. Dmitriy Yakubovskiy d.iakubovskiy@sysiq.com
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×