最新消息:

javascript脚本加载 js load block

javascript admin 3163浏览 0评论

p_543_001
心细的用户,可以从上面的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技巧。

&lt;html&gt;
&lt;head&gt;
&lt;script type="text/javascript"&gt;
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');
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;img src="http://static.perfgeeks.com/wp-content/uploads/2011/01/p_460_001.jpg" /&gt;
&lt;/body&gt;
&lt;/html&gt;<a href="https://pic.aikaiyuan.com/wp-content/uploads/2013/05/p_543_002.jpg"><img class="attachment-full" alt="p_543_002" src="https://pic.aikaiyuan.com/wp-content/uploads/2013/05/p_543_002.jpg" width="923" height="115" /></a>

上图可以看到,a.js, b.js和图片资源并行加载。但是XHR Injection有一个限制,不支持跨域加载。即获取的脚本必须部署在与页面相同的域中。同时,该技术不能保证脚本的执行顺序。

Script DOM Element

相较于XHR Injection而言,Script DOM Element技巧支持跨域加载,即可以加载来自不同域的text/javascript资源文件。这是因为该技术利用javascript动态创建script DOM元素并且设置src。

&lt;html&gt;
&lt;head&gt;
&lt;script type="text/javascript"&gt;
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');
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;img src="http://static.perfgeeks.com/wp-content/uploads/2011/01/p_460_001.jpg" /&gt;
&lt;/body&gt;
&lt;/html&gt;<a href="https://pic.aikaiyuan.com/wp-content/uploads/2013/05/p_543_003.jpg"><img class="attachment-full" alt="p_543_003" src="https://pic.aikaiyuan.com/wp-content/uploads/2013/05/p_543_003.jpg" width="841" height="116" /></a>

上图也解决了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;
}

p_543_004
二幅图对比,我们可以看到那条竖着的蓝线,表示脚本渲染完成。使用script src技术,则等到c.php(text/javascrip)加载完成之后完成的渲染。而使用XHR Injection技术加载脚本,并没有阻塞渲染。
阻塞onload,通常页面的onload要直到所有资源加载完成时才会被触发。如果加载一个较大的javascript文件,用户需要等待更长时间,浏览器状态栏才会显示“完成”,同时还有可能延迟默认输入框获取焦点。导致较差的用户体验。
执行顺序,当一个页面包含多个text/javascript脚本文件的时候。这些高级技术,使得这些脚本同时(并行)加载,受网络与文件大小的影响,脚本文件到到达顺序与开发人员期望的顺序有可能不一致。所以,使用这些高级技术的时候,尽量避免将相互调用的函数分散在不同的文件里面。

转载请注明:爱开源 » javascript脚本加载 js load block

您必须 登录 才能发表评论!