YAOHAIXIAO.COM

HTML(5),CSS(3),JavaScript,DOM,Ajax,JSON,Front-end technologies & Yaohaixiao

热门标签:JavaScript Performance 前端开发 前端性能优化 原创

Rss

Home » Frontend » Performance » 前端性能优化:Prefer asynchronous resources

前端性能优化:Prefer asynchronous resources

今天介绍 PageSpeed 的前端性能优化规则是:Prefer asynchronous resources(首选异步资源)。

Prefer asynchronous resources 的目的

在 PageSpeed 的文档中很简单明了的说明了为什么要首选异步资源:

Fetching resources asynchronously prevents those resources from blocking the page load.

直接翻译上面文档大意是这样的:异步获取资源可以防止这些(JavaScript 脚本)资源阻塞页面加载,避免影响下载速度。

在前面介绍 Put JavaScript at bottom 规则时我们提到过 JavaScript 的加载会阻塞页面加载。PageSpeed 的这个规则实际上就是是针对加载 JavaScript 脚本文件的性能优化规则。PageSpeed的文档也进一步说明了一步加载JavaScript脚本的好处:

With an asynchronous script, however, the browser can continue parsing and rendering HTML that comes after the async script, without waiting for that script to complete. When a script is loaded asynchronously, it is fetched as soon as possible, but its execution is deferred until the browser’s UI thread is not busy doing something else, such as rendering the web page.

当采用异步方式加载 JavaScript 脚本时,浏览器可以继续下载,解析和渲染在这个异步脚本之后的组件和HTML页面,不会产生阻塞页面加载其他组件的问题。当JavaScript脚本采用异步加载是,浏览器会等待完成其他所有 UI 线程的处理完毕以后再立刻执行脚本加载和执行处理。这句话的意思就是,采用异步加载方式加载JavaScript脚本,即可以充分利用浏览器资源尽快完成UI界面的渲染,可以让用户立刻看到 UI 界面,看到感兴趣的信息,又可以在左右UI渲染后成后,利用全部的浏览器资源快速的执行JavaScript相关的操作,达到优化前端性能的目的。

Prefer asynchronous resources

知道异步加载脚本对优化前端性能的好处之后,我们就要看看如何实践 Prefer asynchronous resources。不够在讲解如何实践以前,我们需要了解什么样的 JavaScript 资源应当采用异步加载:

什么样的 JavaScript 资源应当采用异步加载

JavaScript resources that aren’t needed to construct the initial view of the web page, such as those used for tracking/analytics, should be loaded asynchronously. Some scripts that display user-visible content may also be loaded asynchronously, especially if that content is not the most important content on the page.

构建网页的初始视图不需要的JavaScript资源,例如页面中的跟踪和信息统计代码,应该采用异步加载。一些用来显示用户可见的内容部分的脚本也可以被异步加载,特别是如果该内容是不是在页面上的最重要的内容,也应该采用异步加载。例如在页面底部的内容。

如何实现异步加载 JavaScript 资源

现在我们要做的就是具体的实现方法了,PageSpeed文档给了我们一个完整的解决方案:

<script>
var node = document.createElement('script');
node.type = 'text/javascript';
// add async attribute Internet Explorer, Firefox, Chrome, and Safari
// will loading JavaScript asynchronous
node.async = true;
node.src = 'example.js';
// Now insert the node into the DOM, perhaps using insertBefore()
</script>

使用 document.createElement() 方法动态创建一个 SCRIPT DOM节点,然后将动态创建的SCRIPT节点添加到HTML文档中。很容易不是吗?

Using a script DOM element with an async attribute allows for asynchronous loading in Internet Explorer, Firefox, Chrome, and Safari. By contrast, at the time of this writing, an HTML <script> tag with an async attribute will only load asynchronously in Chrome or Firefox 3.6 or newer, as other browsers do not yet support this mechanism for asynchronous loading.

这里要特别说明的一点是,在创建SCRIPT节点时PageSpeed的解决方案中给SCRIPT节点添加了一个重要的属性/值:async=true。有了这个属性, Internet Explorer、Firefox、Chrome 和 Safari 浏览器都会异步加载SRC属性中指定的外部JavaScript资源,可以做到对主流浏览器的兼容。如果忘记了添加 async=true 属性/值,则只有 Chrome 和 Firefox 3.6+ 版本的浏览器会异步加载,其余的浏览器则还是会采用阻塞式的加载方式了。

动态创建 SCRIPT 的一点扩展内容

前面介绍了动态创建SCRIPT标签的方法,不过我们实际的情况往往不只是单传的创建一个SCRIPT节点加载JavaScript资源,很多时候我们是希望在脚本加载完毕之后执行相关的操作,这个时候我们要如何处理呢?

Nicholas C. Zakas 的博文《Loading JavaScript without blocking》中介绍了怎么操作,大家可以看看。不过 Zakas 给出的解决方案里没有添加 async=true 属性/值,这里我就直接把微调后的代码贴出:

function loadScript(url, callback){

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

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

    script.src = url;
    document.body.appendChild(script);
}

相关阅读

声明:本文采用BY-NC-SA协议进行授权。转载请注明转自:前端性能优化:Prefer asynchronous resources

« »

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(Spamcheck Enabled)