js load js

javascript腳本加載 js load block


心細的用戶,可以從上面的http瀑布圖比較看出:只有等到a.js加載完了,纔開始加載b.js,然後再加載圖片資源。我們稱a.js阻塞b.js。這種現象,稱之爲js load block。

//filename:index.html
<html>
<head>
  <script type="text/javascript" src="a.js"></script>
  <script type="text/javascript" src="b.js"></script>
</head>
<body>
  <img src="http://static.perfgeeks.com/wp-content/uploads/2011/01/p_460_001.jpg" />
</body>
</html>

有沒有辦法,讓這三個不同的資源a.js, b.js, p_460_001.jpg同時加載,減少頁面加載時間,避免因阻塞導致的減速影響。通常有以下幾個辦法

  • 把所有javascript都內嵌在頁面中
  • XHR Eval
  • XHR Injection
  • Iframe
  • Script DOM Element
  • Defer
  • document.write

這裏着重介紹最常用的XHR Injection和Script DOM Element二種方法

XHR Injection

XHR Injection和XHR Eval注入技巧都是通過XMLHttpRequest來獲取Javascript腳本資源。然後,XHR Eval通過javascript函數eval執行腳本。而XHR Injection則是通過創建一個script的DOM元素,然後把XMLHttpRequest的響應注入script中。某些時候,eval會比較慢,所以我們不推薦使用XHR Eval技巧。

<html>
<head>
<script type="text/javascript">
function load_js(src) {
    var xml_http = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
    xml_http.onreadystatechange = function() {
      if (xml_http.readyState == 4) {
         var script_element = document.createElement('script');
         document.getElementsByTagName('head')[0].appendChild(script_element);
         script_element.text = xml_http.responseText;
      }
    }
    xml_http.open('GET', src, true);
    xml_http.send('');
}
load_js('a.js');
load_js('b.js');
</script>
</head>
<body>
<img src="http://static.perfgeeks.com/wp-content/uploads/2011/01/p_460_001.jpg" />
</body>
</html>


上圖可以看到,a.js, b.js和圖片資源並行加載。但是XHR Injection有一個限制,不支持跨域加載。即獲取的腳本必須部署在與頁面相同的域中。同時,該技術不能保證腳本的執行順序。

Script DOM Element

相較於XHR Injection而言,Script DOM Element技巧支持跨域加載,即可以加載來自不同域的text/javascript資源文件。這是因爲該技術利用javascript動態創建script DOM元素並且設置src。

<html>
<head>
<script type="text/javascript">
function load_js(src) {
  var script_elem = document.createElement('script');
  script_elem.type = 'text/javascript';
  script_elem.src = src;
  document.getElementsByTagName('head')[0].appendChild(script_elem);
}
load_js('a.js');
load_js('b.js');
load_js('http://www.jt-tech.net/misc/jquery.js');
</script>
</head>
<body>
<img src="http://static.perfgeeks.com/wp-content/uploads/2011/01/p_460_001.jpg" />
</body>
</html>


上圖也解決了javascript加載阻塞產生的減速影響,即a.js、b.js還有跨域jquery.js等並行加載。這種技巧也有一個小小缺陷,就是在某些瀏覽器(Firefox2.0/3.0/3.1、Safari3.2.1/4.0、Chrome1.0)會阻塞onload事件,影響用戶體驗

阻塞渲染、阻塞onload、執行順序

阻塞渲染,當使用script src技術加載腳本時,瀏覽器停止渲染所有腳本後面的內容。這種阻塞給用戶帶來十分差勁的用戶體驗。應該儘量地避免這種情況出現。

//filename:cat bd_i.html
<html>
<head>
<script type="text/javascript" src="c.php">
</script>
</head>
<body>
hello world
</body>
</html>
 
//filename:vbd_i.html
<html>
<head>
<script type="text/javascript">
function load_js(src) {
    var xml_http = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
    xml_http.onreadystatechange = function() {
      if (xml_http.readyState == 4) {
         var script_element = document.createElement('script');
         document.getElementsByTagName('head')[0].appendChild(script_element);
         script_element.text = xml_http.responseText;
         script_element.type = 'text/javascript';
      }
    }
    xml_http.open('GET', src, true);
    xml_http.send('');
}
load_js('c.php');
</script>
</head>
<body>
hello world
</body>
</html>
 
//filename: c.php
<?php
sleep(2);
?>
function c() {
  return 2;
}


二幅圖對比,我們可以看到那條豎着的藍線,表示腳本渲染完成。使用script src技術,則等到c.php(text/javascrip)加載完成之後完成的渲染。而使用XHR Injection技術加載腳本,並沒有阻塞渲染。
阻塞onload,通常頁面的onload要直到所有資源加載完成時纔會被觸發。如果加載一個較大的javascript文件,用戶需要等待更長時間,瀏覽器狀態欄纔會顯示“完成”,同時還有可能延遲默認輸入框獲取焦點。導致較差的用戶體驗。
執行順序,當一個頁面包含多個text/javascript腳本文件的時候。這些高級技術,使得這些腳本同時(並行)加載,受網絡與文件大小的影響,腳本文件到到達順序與開發人員期望的順序有可能不一致。所以,使用這些高級技術的時候,儘量避免將相互調用的函數分散在不同的文件裏面。

發佈了49 篇原創文章 · 獲贊 82 · 訪問量 68萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章