手机版

JavaScript中的无阻塞加载性能优化方案

时间:2021-09-09 来源:互联网 编辑:宝哥软件园 浏览:

浏览器中Javascript的性能是前端开发人员必须面对的最重要的可用性问题。

在雅虎的Yslow23规则中,有一条是把JS放在最下面。究其原因,其实大多数浏览器都是用一个单一的进程来处理UI、Javascript更新等多个任务,一次只能执行一个任务。只要Javascript运行,浏览器空闲响应用户交互之前,会有很长的等待时间。

基本上,这意味着脚本标签的出现使整个页面等待脚本解析和运行。无论实际的JavaScript代码是内联的还是包含在不相关的外部文件中,页面下载和解析过程都必须停止,等待脚本完成这些过程后才能继续。这是页面生命周期中必不可少的一部分,因为脚本可能会在运行时修改页面内容。一个典型的例子是document.write()函数,例如,复制代码如下: html头部标题脚本示例/title/头部正文p脚本类型=' text/JavaScript ' document . write(' date is '(new date())。to date string());/script/p/body/HTMl当浏览器遇到脚本标记时,就像上面的html页面一样,无法预测JavaScript是否会向p标记添加内容。因此,浏览器停止,运行这个JavaScript代码,然后继续解析和翻译页面。在加载带有src属性的JavaScript的过程中也发生了同样的事情。浏览器必须首先下载外部文件的代码,这需要一些时间,然后解析并运行代码。在这个过程中,页面解析和用户交互被完全阻断。

因为脚本会阻塞其他页面资源的下载过程,所以推荐的方法是将所有脚本标签尽可能靠近:中的body标签的底部,以最大限度地减少对整个页面下载的影响。例如,复制代码如下: html head title脚本示例/title link rel='样式表' type=' text/CSS ' href=' styles . CSS '/head body p hello world!/p -推荐的脚本定位示例-脚本类型=' text/JavaScript ' src=' http : file 1 . js '/脚本类型=' text/JavaScript ' src=' http : file 2 . js '/脚本类型=' text/JavaScript ' src=' http : file 3 . js '/脚本/正文/html

这段代码显示了推荐的脚本标签在HTML文件中的位置。虽然脚本下载互相屏蔽,但页面已经下载并显示在用户面前,所以进入页面的速度不会显得太慢。这就是上面提到的把JS放在底部。

另外,雅虎!对于他的“雅虎!用户界面(雅虎!用户界面,YUI)图书馆创建了一个“联合手柄”,这是通过他们的“内容交付网络”实现的。任何网站都可以使用“联合句柄”URL来指示YUI包中包含哪些文件。例如,以下URL包含两个文件:复制代码:脚本类型=' text/JavaScript ' src=' http :http://yui.yahoaips.com/combo? 2 . 7 . 0/build/Yahoo/Yahoo-min . js 2 . 7 . 0/build/event/event-min . js '/脚本

该网址调用2.7.0版的yahoo-min.js和event-min.js文件。这些文件在服务器上是两个独立的文件,但是当服务器收到这个网址请求时,这两个文件将被合并并返回给客户端。这样,不再需要两个脚本标签(每个标签一个文件),一个脚本标签可以加载它们。这是在HTML页面中包含多个外部Javascript的最佳方式。

非阻塞脚本

以上是在页面初始状态下加载多个Javascript脚本的最佳方式。Javascript倾向于阻塞一些浏览器处理过程,比如http请求和界面刷新,这是开发人员面临的最显著的性能问题。保持Javascript文件的简短并限制http请求的数量只是创建快速响应web应用程序的第一步。

然而,例如,大型网页有大量的Js代码,所以保持源代码简短并不总是最好的选择。于是,无阻塞脚本应运而生。我们需要的是一步一步给页面添加javascript,这样不会在一定程度上阻塞浏览器。

非阻塞脚本的关键是页面加载后加载Javascript源代码,也就是说在window的load事件发出后才会下载代码。

相关说明:

窗口的加载事件仅触发一次,并且仅在页面加载后触发一次。Window.onload=function(){}在网页中的所有内容(包括元素的所有关联文件,如图片)加载完毕后才能执行,也就是说此时Javascript可以访问页面中的任何元素。

有以下几种方法:

延期脚本延期脚本

Html4为脚本标签定义了一个扩展属性:defer。

这个延迟属性表明元素中包含的脚本并不打算修改DOM,所以代码可以稍后执行。延期属性只有Internet Explorer 4和Firefox 3.5支持,这不是一个理想的跨浏览器解决方案。在其他浏览器上,延迟属性被忽略。因此,脚本标记将以正常的默认方式进行处理,也就是说,它会导致阻塞。如果得到各种主流浏览器的支持,这仍然是一个有效的解决方案。复制代码的代码如下: script type=' text/JavaScript ' src=' http 3360 file 1 . js ' delay/script

具有defer属性的脚本标记可以放在文档中的任何地方,当解析它时,它将开始下载,直到加载DOM(在调用onload事件句柄之前)。下载defer的Javascript文件时,不会阻塞浏览器的其他进程,所以这些文件可以和其他资源并行下载。

您可以使用以下代码来测试浏览器是否支持delay属性:按如下方式复制代码: html headtitle脚本delay示例/title/headbody脚本delay alert(' delay ');/script脚本警报('脚本');/script script window . onload=function(){ alert(' load ');};/脚本/正文/html

如果浏览器不支持延期,弹出对话框的顺序为“延期”、“脚本”和“加载”。

如果浏览器支持延期,弹出对话框的顺序为“脚本”、“加载”和“延期”。

动态脚本元素动态脚本元素

DOM允许我们使用Javascript动态创建HTML的几乎所有文档内容,并且可以通过标准DOM轻松创建一个新的脚本元素:

复制代码如下:1 var script=document . create element(' script ');2 script . type=' text/JavaScript ';3 script . src=' file 1 . js ';4 document.body.appendChild(脚本);

新的脚本元素加载file1.js源文件。一旦元素被添加到页面,该文件就开始下载。这项技术的关键点在于,无论从哪里开始下载,文件的下载和运行都不会阻塞其他页面处理过程。

当使用动态脚本节点下载文件时,返回的代码通常会立即执行(火狐和Opera除外,它们将等待所有以前的动态脚本节点完成执行)。

在大多数情况下,我们希望调用一个函数来动态下载Javascript文件。以下功能封装实现了标准实现和IE实现:

复制代码如下:函数loadscript (URL,回调){ var script=document . create element(' script ');script . type=' text/JavaScript ';if(script . readystate){//IE script . onreadystatechange=function(){ if(script . readystate==' loaded ' | | script . readystate==' complete '){ script . onreadystatechange=null;回调();} };} else {//Others script . onload=function(){ callback();};} script.src=urldocument . getelementsbytagname(' head ')[0]。appendChild(脚本);} loadscript ('file1.js ',function(){//调用alert('File已加载!');});

这个函数接受两个参数:Javascript文件的Url和接收到Javascript时触发的回调函数。属性检查用于决定监视哪些事件。最后一步是src属性,并在头部添加javascript文件。

动态脚本加载是非阻塞式Javascript下载中最常用的模式,因为它可以跨浏览器,并且易于使用。

Xmlhttprequest脚本注入xhr脚本注入

以非阻塞方式获取脚本的另一种方法是使用XMLHttpRequest(XHR)对象将脚本注入页面。这项技术首先创建一个XHR对象,然后下载Javascript文件,然后用动态脚本元素将Javascript代码注入页面。请参见演示:

复制代码如下: var xhr=new XMLHttpRequest();xhr.open('get ',' file1.js ',true);xhr . onreadystatechange=function(){ if(xhr . readystate==4){ if(xhr . status=200 xhr . status 300 | | xhr . status==304){//检查http状态代码varscript=document . create element(' script ');script . type=' text/JavaScript ';script . text=xhr . responsetext;document.body.appendChild(脚本);} }};xhr . send(null);

这段代码向服务器发送file1.js的文件获取请求。onreadyStatechange事件处理程序检查readystate是否为4,然后检查http状态代码是否有效(200表示客户端请求成功,2xx表示有效响应,304表示缓存响应)。如果收到有效的响应,将创建一个新的脚本元素,并将它的文本属性设置为从服务器收到的响应文本字符串。这样做实际上会用内联代码创建一个脚本元素。一旦新的脚本元素被添加到文档中,代码将被执行并准备使用。

这种方法的优点是兼容性好,可以下载不立即执行的Javascript代码。由于代码在脚本标记之外返回,下载后不会自动执行,这允许您推迟执行。

这种方式受到浏览器同源性的限制,Javascript文件必须和页面放在同一个域,不能从CDN (Content Delivery Network)下载。因此,XHR脚本注入技术通常不用于大型网页。

推荐的无阻塞模式推荐的非阻塞模式

将大量Javascript加载到页面中的推荐方法分为两个步骤:

第一步是包含动态加载Javascript所需的代码,然后加载除了页面初始化所需的Javascript之外的部分。这部分代码尽可能小,可能只包含loadScript()函数。可以非常快速的下载运行,不会对页面造成很大的干扰。

第二,当初始代码准备好了,用它来加载剩下的Javascript。

例如,复制代码如下:1 Script Type=' text/JavaScript ' src=' http : loader . js ' 2/Script Script Type=' text/JavaScript ' 3 loadscript(' the-rest . js ',function(){ 4 application . init();5 });6 7/脚本将此代码放在body的结束标记/body之前。这样做的好处是,首先保证了Javascript不会影响其他页面其他部分的显示。其次,当Javascript文件的第二部分被下载时,应用程序所需的所有DOM都已经被创建,并准备好被访问。避免使用额外的事件处理(如window.onload)来知道页面是否准备好了。

另一种选择是将loadScript()函数直接嵌入到页面中,这样可以减少http请求的开销。例如:

复制的代码如下:1脚本类型=' text/JavaScript '函数loadscript (URL,回调){ var script=document . create element(' script ');script . type=' text/JavaScript ';if(script . readystate){//IE script . onreadystatechange=function(){ if(script . readystate==' loaded ' | | script . readystate==' complete '){ script . onreadystatechange=null;回调();} };} else {//Others script . onload=function(){ callback();};} script.src=urldocument . getelementsbytagname(' head ')[0]。appendChild(脚本);}loadScript('the-rest.js ',function(){ application . init();});/script

下载页面初始化代码后,还可以使用loadScript()函数加载页面所需的其他函数。

介绍一个通用工具,雅虎!Search的Ryan Grove创建了LazyLoad库(参见http://github.com/rg rove/lazy load/)。LazyLoad是一个功能强大的loadScript()函数。LazyLoad缩小后只有1.5KB左右。用法示例如下:复制代码如下: script type=' text/JAVAScript ' src=' http : laziload-min . js '/script type=' text/JAVAScript ' laziload . js '(the-rest . js ',function(){ application . init();});/script

摘要摘要

1.将所有脚本标签放在页面底部,就在结束标签/正文上方。此方法可以确保在脚本运行之前解析页面。

2.分组打包脚本。页面的脚本标签越少,页面加载和响应的速度就越快。外部脚本文件和内联代码都是如此。

3.有几种方法可以以非阻塞方式下载Javascript:

1).将延迟属性添加到脚本标签2)。动态创建脚本元素,并使用它来下载和执行代码3)。下载带有XHR对象的代码,并将其注入页面

通过以上策略,使用Javascript代码的用户的实际性能可以得到很大的提升。

参考书《高性能Javascript》。

版权声明:JavaScript中的无阻塞加载性能优化方案是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。