通过延缓执行 JavaScript 提升网页加载速度

坦诚相待 发布于 2012/04/12 14:37
阅读 2K+
收藏 27

简介


延缓执行 JavaScript 是一个能有效提高网页加载速度以及提升用户阅读体验质量的途径。从实际经验来看,将我们的网站从经济实惠的 VPS 迁移到 Softlayer(美国著名的一个数据中心)独立服务器平台上只能给网站加载速度带来20%的提升,但是通过延缓执行 JavaScript 却能帮助提速 50% ,不妨看看 Google Webmaster 工具 > Site Performance(网站性能)的统计结果:

 

实战

网页开发遵循一个假设,就算有 JS 文件突然被中断了,只要没有 JS 执行错误,那网页就一定会被正确渲染。简单的说,延缓执行 JS 可以采取下面两种规则:

  1. 等到页面 Document 准备好之后再来执行内联的 JS 代码,这些代码至少也得放在页面底部。

  2. 动态地加载外部 JavaScript 文件。如果多个 JS 文件之间存在依赖,确保主要的 JS 文件引用写在网页底部以便最后加载。
下面这个主页面的代码片段指出了我们如何在开发中延缓 JavaScript 的执行。 

<script type="text/javascript">// <![CDATA[
        _lazyLoadScripts = new Array();
        _lazyExecutedCallbacks = new Array();
// ]]></script>
<script type="text/javascript" src="/scripts/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="/scripts/website-lazy-load.js"></script>

在开发中经常会有些嵌套网页或者构件需要依赖一些外部 JS 文件或 JS 代码的执行。在这种情况下,可以像上面例子那样在主页面顶部定义两个变量 “_lazyLoadScripts” 和 “_lazyExecutedCallbacks” 。

在下面代码片段中,你可以看到这两个变量是如何被使用在嵌套网页或构件上的。

<script type="text/javascript">// <![CDATA[
    _lazyExecutedCallbacks.push(function ()
    {
        // in the case you need to execute some scripts in a nested page or module.
        // don't execute them explicitly, but push them into the callback list.
    });
// ]]></script>
<script type="text/javascript">// <![CDATA[
    // push the external JS files into the list for deferring loading.
    _lazyLoadScripts.push("/scripts/your-script.js");
// ]]></script>

这些被压入(push)到 “_lazyExecutedCallbacks” 里的 JS 代码和被插入到 “_lazyLoadScripts” 里的外部 JS 文件全部都会在 “website-lazy-load.js” 里被执行,执行的代码片段如下:

// dynamically load external JS files when document ready
// dynamically load external JS files when document ready
function loadScriptsAfterDocumentReady()
{
    if (_lazyLoadScripts && _lazyLoadScripts != null)
    {
        for (var i = 0; i < _lazyLoadScripts.length; i++)
        {
            var scriptTag = document.createElement('script');
            scriptTag.type = 'text/javascript';
            scriptTag.src = _lazyLoadScripts[i];
            var firstScriptTag = document.getElementsByTagName('script')[0];
            firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag);
        }
    }
}
 
// Execute the callback when document ready.
function invokeLazyExecutedCallbacks()
{
    if (_lazyExecutedCallbacks && _lazyExecutedCallbacks.length > 0)
        for(var i=0; i<_lazyExecutedCallbacks.length; i++)
            _lazyExecutedCallbacks[i]();
}
 
// execute all deferring JS when document is ready by using jQuery.
jQuery(document).ready(function ()
{
    loadScriptsAfterDocumentReady();
    invokeLazyExecutedCallbacks();
});

小贴士

  1. 开发网页的合理步骤应该是首先编写 HTML 和 CSS 。等这些网页在浏览器里能够正确地(符合你的期望)被渲染出来之后,再开始编写 JS 代码来支持动画或者其他的效果。

  2. 不要在 HTML 页面上的任何一个元素上编写 onclick="..." 代码来绑定事件,但是可以在 HTML Document 都准备好的情况下进行绑定。这样可以避免在 JS 文件加载完成之前因用户触发了 onclick 事件而导致的 JS 错误。

  3. 如果你的网站需要广泛地加载外部 JS 文件,那么将它们写在 “website-lazy-load.js” 里动态的加载进来,例如 Google Analytics tracking 的JS 文件、 Google AdSense 的JS 文件等等。

  4. 这种方法同样地对 CSS 文件也有效。但是别对 主CSS 文件这么做。
英文原文,OSChina原创翻译。

加载中
0
Ken
Ken
<![CDATA[ ...  // ]]> 请教下,这种写法是什么意思啊?
坦诚相待
坦诚相待
这是一个经常在js代码块里添加的错误预防措施,他是在处理真正的XHTML文档(“application/xhtml+xml” content-type)时为了防止代码将形如<号解析为标签开始,所有在CDATA内包含的内容,都会被当成文本处理。但是实际情况是,目前几乎所有的网页的content-type都是text/html,也就是说它们不是严格意义上的xml文档,而是只是text文本,所以这个错误预防处理措施是完全没有必要的,即使你确定要支持xml的文档,也要视情况合理的运用CDATA。
0
0
zbzcyeq
zbzcyeq
学习了!!谢谢啊
0
surgesoft
surgesoft
website-lazy-load.js在哪里可以找到吗
0
daxnight
daxnight
关于小贴士第二点:不在元素上编写 onclick。请教一下LZ,改用什么方法好一点呢?我平时都是用这种的。js菜鸟请教。
0
高榕
高榕

引用来自“daxnight”的答案

关于小贴士第二点:不在元素上编写 onclick。请教一下LZ,改用什么方法好一点呢?我平时都是用这种的。js菜鸟请教。

用jq啊,在

$(document).ready(function(){

    $("#button").on('click',function(){

        alert(1111);

    })

})

0
daxnight
daxnight
页面加载时开始绑定。谢谢!还可以用Js的onload添加事件监听了。
0
幽烛
幽烛
 多谢 用到咯
返回顶部
顶部