视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
加载Javascript最佳实践_javascript技巧
2020-11-27 21:01:18 责编:小采
文档


相信很多与页面打过交道的同学都对 Yahoo 的 Best Practices for Speeding Up Your Web Site 不陌生。而这 35 条最佳实践中,对 Javascript 的加载顺序的要求是:Put Scripts at the Bottom。因为根据 HTTP/1.1 specification 看来,在同一时间加载两个文件是最理想的,而 Javascript 脚本会阻碍平行下载。Steve 说那是 2008 – 2009 那个时代用的。现在,加载 Javascript 已经有了性的化变。

javascript-download

在开讲之前,有一个必须解决的问题是:为什么我们要把 JS 文件放在

之前的最底部。根本原因是,它不能平行下载。而其实并不是所有浏览器都不支持。现在大部分浏览器都支持 Script 的平行下载,除了老掉牙的 IE6&7、Firefox 2&3.0、 Safari 3、Chrome 1。但我们最熟悉的老掉牙同学 IE6 (或以IE为核的那些壳)还是中国(甚至世界上)市场上占用率最高的浏览器,因此我们需要一个折衷的方案。

一、分析

我们有6种方法可以实现平行(NON-Blocking)下载:

  • XHR Eval – 用 XHR 下载,并 eval() 执行 responseText.。
  • XHR Injection – 用 XHR 下载,在页面中动态创建一个 script 元素,并将 responseText 作为其 text
  • Script in Iframe – 把脚本放在 HTML 中,使用 ifame 来下载它。
  • Script DOM Element – 动态创建一个 script 元素,把 src 指向脚本URL.
  • Script Defer – 给 script 标添加 defer 属性
  • document.write Script Tag – 利用 document.write 添加到 HTML 中。但这个只对 IE 有效。
  • 兼容性可看下图:

    Technique Parallel Downloads Differ Existing Scripts Busy Indicators Ensures Order Size (bytes)
    XHR Eval IE, FF, Saf, Chr, Op no no Saf, Chr - ~500
    XHR Injection IE, FF, Saf, Chr, Op no yes Saf, Chr - ~500
    Script in Iframe IE, FF, Saf, Chr, Op no no IE, FF, Saf, Chr - ~50
    Script DOM Element IE, FF, Saf, Chr, Op yes yes FF, Saf, Chr FF, Op ~200
    Script Defer IE, Saf4, Chr2, FF3.1 yes yes IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op ~50
    document.write Script Tag IE, Saf4, Chr2, Op yes yes IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op ~100

    二、方案

    对于究竟应该使用哪种方案。这完全取决于你需要自身的需要。这张图描述了什么时候使用什么方法:

    0405-load-scripts-decision-tree-04

    从总体上看来,Script DOM Element 是比较好的方案。NCZ 的博客上提过,目前最好的技术是:

    1. 创建两个 JavaScript 文件。第一个文件只提供动态下载 Javascript 的代码,第二个文件则包含所有其他页面所需脚本的文件。
    2. 在页部(
      之前
      )引入第一个文件。
    3. 创建第二个 来执行下载第二个 Javascript 文件的函数和其他的初始化代码。

    三、实现代码

    根据上面的提到的技术。NCZ 推荐第一个文件只包含相应的实现第二个文件动态加载的代码:
    代码如下:
    function loadScript(url, callback){

    var script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState){ //IE
    script.onreadystatechange = function(){
    if (script.readyState == "loaded" ||
    script.readyState == "complete"){
    script.onreadystatechange = null;
    callback();
    }
    };
    } else { //Others
    script.onload = function(){
    callback();
    };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
    }

    然后,我们可以在页面中这样做:
    代码如下:


    loadScript("http://your.cdn.com/second.js", function(){
    //初始化你的代码
    });


    在 HTML5 上,我们可以使用 async 属性。这个 HTML 属性的作用正是我们需要的 NON-Blocking 下载技术。虽然目前支持的浏览器并不多(似乎只有 Firefox 3.6+ ?),但给需要平行下载的 Javascript(按照方案看来,一般是第一个 JS 文件) 加上这个属性,也不会影响其他不支持的浏览器,所以,是推荐使用的。
    代码如下:
    四、实践
    YUI3 的 Loader 使用了 NCZ 的这样的方法。而在支付宝。我们也使用了类似的方法。这里简单说一下。
    代码如下:

    // 配置 combo 服务的 PATH
    araleConfig = {
    combo_host: "http://domain.com",
    combo_path: '/path/to/the/compressed/file'
    }



    在使用的时候,再利用 Loader.use() 来实现代码的动态加载。当然,这里不仅仅是动态加载,还有一定的缓存机制在里面。建议你查看相关的 combo 服务的技术。目前支付宝前端架构组的工友们,已经在这一块取得了一些不错的进展(根据测试报告,速度是非常不错的,可能会在适当的时候开源出来)。

    五、总结
    前端性能优化方面。还有很多东西可以做。并且,随着 HTML5 技术的出现和 Javascript 技术的不断创新,相信还有更多东西是值得期待。前端们,加油吧,未来有很多东西应该是由你来主导的。

    Reference:

    1. Loading Scripts Without Blocking
    2. The best way to load external JavaScript
    3. Evolution of Script Loading
    4. What is a non-blocking script?
    5. HTML5 – Scripting: async Attribute

    下载本文
    显示全文
    专题