性能优化之无阻塞加载脚步方法比较

秋招结束了~~,好像偷懒了很久,没更博了。总结一下自己近来看书的内容。

说明一下,内容大部分来自《高性能网站建设进阶指南》。

乱入内容

Web应用和传统桌面应用有一个共同的目标:尽可能快地响应用户输入。

怎样才算是快?Jakob Nielsen是Web可用性领域知名且备受推崇的专家,引用他的观点来说就是:如果JavaScript代码执行时间超过了0.1秒,页面将会给人不够平滑快捷的感觉,如果执行时间超过了1秒,则会感到应用程序缓慢,超过了10秒,那么用户将会非常沮丧。

性能分析器:Firebug性能分析器

当延迟变得很严重时:线程处理Web Workers、Gears

无阻塞加载脚步

script标签的阻塞行为会对页面性能产生负面影响。大多数浏览器在下载或执行脚本的同时不会下载其他内容。有时候这种阻塞是非必要的。所以,有些情况我们希望以不阻塞其他内容下载的方式来加载JavaScript。可以做到这点使页面加载更快的有:

1.XHR Eval

2.XHR注入

3.Script in Iframe

4.Script DOM Element

5.Script Defer

6.document.write Script Tag

①XHR Eval

比较好理解,就是为了并行加载更多的脚本,把一些脚本拆分,然后通过ajax的方式请求脚本,再通过eval来执行。

实例代码:

   var xhrObj=getXHRObject();
   xhrObj.onreadystatechange=function(){
      if(xhrObj.readyState==4&&200==xhrObj.status){
         eval(xhrObj.responseText);
      }
  };
xhrObj.open(‘GET‘,‘A.js‘,true);
xhrObj.send(‘ ‘);

//获取XHR对象的基本方法
function getXHRObject (){
   if (typeof XMLHttpRequest != "undefined"){
          return new XMLHttpRequest();
   } else if (typeof ActiveXObject != "undefined"){
 if (typeof arguments.callee.activeXString != "string"){
     var versions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
          "MSXML2.XMLHttp"],
          i, len;
     for (i=0,len=versions.length; i < len; i++){
     try {
        new ActiveXObject(versions[i]);
        arguments.callee.activeXString = versions[i];
        break;
     } catch (ex){
       //跳过
     }
    }
  }
   return new ActiveXObject(arguments.callee.activeXString);
  } else {
      throw new Error("No XHR object available.");
  }
}

缺点:

  通过XMLHttpRequest获取的脚本必须部署在和主页面相同的域中。

②XHR注入

类似于XHR Eval,XHR注入技术也是通过XMLHttpRequest来获取JavaScript的,但与eval不同的是,该机制通过创建一个script的DOM元素,然后把XMLHttpRequest的响应注入script中来执行JavaScript的,某些情况下使用这种机制的性能会优于eval。

示例代码:

   var xhrObj=getXHRObject();
   xhrObj.onreadystatechange=function(){
      if(xhrObj.readyState==4){
         var scriptElem=document.createElement(‘script‘);
         document.getElementsByTagName(‘head‘)[0].appendChild(scriptElem);
         scriptElem.text=xhrObj.responseText;
      }
  };
xhrObj.open(‘GET‘,‘A.js‘,true);
xhrObj.send(‘ ‘);

③Script in Iframe

主页中的iframe和其他组件是并行加载的,与用iframe在一个HTML页面中包含另一个页面的传统做法不同,Script in Iframe技术利用iframe无阻塞加载JavaScript,实现过程完全在HTML中完成。

示例代码:

<iframe src=‘A.html‘ width=0 height=0 frameborder=0 id=‘frame1‘></ifame>

缺点:

该技术使用了A.html,而不是A.js,因为iframe认为其返回的是HTML文档。所有我们要做的就是在HTML文档中把外部脚本转换为行内脚本。并且要求iframe和主页面同域。

附访问iframe的方法:

1.通过frames数组:window.frames[0]

2.通过document.getElementById访问。

④Script DOM Element

利用script标签,动态创建脚本,创建script元素,并设置其src值。

示例代码:

var scriptElem=document.createElement(‘script‘);
scriptElem,src=‘http://test.js‘;
document.getElementByTagName(‘head‘)[0].appendChild(scriptElem);

⑤Script Defer

非常简单,这个属性的用途是表明脚本在执行时不会影响页面的构造。也就是说,脚本会被延迟到整个页面都解析完毕后再运行。因此,在<script>元素中设置defer属性,相当于告诉浏览器立即下载,但延迟执行。

HTML5规范要求脚本按照它们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于DOMContentLoaded事件执行。在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在DOMContentLoad时间触发前执行,因此最好只包含一个延迟脚本。

示例代码:

<script defer src=‘A.js‘></script>

在这里顺便辨析一下defer属性和async属性

defer属性:IE4.0就出现。defer属声明脚本中将不会有document.write和dom修改。浏览器会并行下载其他有defer属性的script。而不会阻塞页面后续处理。注:所有的defer脚本必须保证按顺序执行的。

    <script type="text/javascript" defer></script>

async属性:HTML5新属性。脚本将在下载后尽快执行,作用同defer,但是不能保证脚本按顺序执行。他们将在onload事件之前完成。

    <script type="text/javascript" defer></script>

Firefox 3.6、Opera 10.5、IE 9和最新的Chrome和Safari都支持async属性。可以同时使用async和defer,这样IE 4之后的所有IE都支持异步加载。

没有async属性,script将立即获取(下载)并执行,期间阻塞了浏览器的后续处理。如果有async属性,那么script将被异步下载并执行,同时浏览器继续后续的处理。

更多参考:https://segmentfault.com/a/1190000006778717

⑥document.write Script Tag

使用document.write把HTML标签script写入页面中。

技术综述

不同情况下的最佳脚本加载技术的决策树

决策树中的六种结果详解

本总结供自己查阅之用,不喜勿喷。。。 

时间: 2024-10-08 10:27:56

性能优化之无阻塞加载脚步方法比较的相关文章

探真无阻塞加载javascript脚本技术,我们会发现很多意想不到的秘密

原文:探真无阻塞加载javascript脚本技术,我们会发现很多意想不到的秘密 下面的图片是我使用firefox和chrome浏览百度首页时候记录的http请求 下面是firefox: 下面是chrome: 在浏览百度首页前我都将浏览器的缓存全部清理掉,让这个场景最接近第一次访问百度首页的情景. 在firefox的请求瀑布图里有个表现非常之明显:就是javascript文件下载完毕后,有一段时间是没有网络请求被处理的,这段时间过后http请求才会接着执行,这段空闲时间就是所谓的http请求被阻塞

无阻塞加载脚本

一个页面,从被请求访问,到用户可以看到页面.操作页面,到最后页面完全加载完毕,中间需要经历一个相当奇幻的过程,这个过程的速度被"web性能师"孜孜不倦.前赴后继的优化.本文讨论的是其中一个优化. 浏览器线程和阻塞 虽然大家耳熟能详的一句话是: JavaScript是单线程的. 但是: 浏览器当然不是单线程的. 浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询.监听用户事件. 这些线程,根据浏览器自身特点以及web标准等等,有的会被浏览

无阻塞加载js,防止因js加载不了影响页面显示

浏览器加载静态资源和js的方式都是线性加载,所以一般情况可以将js放到</body>前,防止UI线程的阻塞. 而某些时候我们既希望js在整个网页的头部就加载,又担心js阻塞导致网站加载缓慢,就可以用到无阻塞加载js技术. Dynamic Script Elements 动态脚本元素 DOM允许我们使用Javascript动态创建HTML的几乎所有文档内容,一个新的<script>元素可以非常容易的通过标准DOM创建: var script = document.createElem

前端性能优化之按需加载(React-router+webpack)

一.什么是按需加载 和异步加载script的目的一样(异步加载script的方法),按需加载/代码切割也可以解决首屏加载的速度. 什么时候需要按需加载 如果是大文件,使用按需加载就十分合适.比如一个近1M的全国城市省市县的json文件,在我首屏加载的时候并不需要引入,而是当用户点击选项的时候才加载.如果不点击,则不会加载.就可以缩短首屏http请求的数量以及时间. 如果是小文件,可以不必太在意按需加载.过多的http请求会导致性能问题. 二.实现按需加载的方法 Webpack打包模块工具实现 R

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

一.js阻塞特性 JS 有个很无语的阻塞特性,就是当浏览器在执行JS 代码时,不能同时做其他任何事情,无论其代码是内嵌的还是外部的. 即<script>每次出现都会让页面等待脚本的解析和执行(不论JS是内嵌的还是外链的),JS代码执行完成后,才继续渲染页面. 二.优化方案 1.尽管脚本的下载过程并不会相互影响,但页面仍然必须等待所有JS下载并执行完成才能继续.所以尽可能将所有<script>标签放置在页面底部,紧靠关闭标签</body>的上方.此方法可以保证页面在脚本运

Web前端性能优化——如何提高页面加载速度

前言:  在同样的网络环境下,两个同样能满足你的需求的网站,一个"Duang"的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页.也许这样讲,各位还不会有太多感触,接下来我列举一组数据:Google网站访问速度每慢400ms就导致用户搜索请 求下降0.59%;Amazon每增加100ms网站延迟将导致收入下降1%;雅虎如果有400ms延迟会导致流量下降5-9%.网站的加载速度严重影响了用户

【转】Web前端性能优化——如何提高页面加载速度

前言:  在同样的网络环境下,两个同样能满足你的需求的网站,一个"Duang"的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页.也许这样讲,各位还不会有太多感触,接下来我列举一组数据:Google网站访问速度每慢400ms就导致用户搜索请 求下降0.59%;Amazon每增加100ms网站延迟将导致收入下降1%;雅虎如果有400ms延迟会导致流量下降5-9%.网站的加载速度严重影响了用户

脚本无阻塞加载

(图片来源:http://www.cnblogs.com/sharpxiajun/p/4072396.html) 这是清除浏览器缓存后,第一次访问百度首页的场景,在Firefox的瀑布图中可以看到:javascript文件下载完毕后,有一段时间没有请求处理.这段时间过后,请求才会接着执行,这段时间就是HTTP请求阻塞. 当浏览器遇到<script>标签时,浏览器会停止处理页面,先执行Javascript代码,然后再继续解析和渲染页面.在这个过程中,页面和用户的交互完全被阻塞了.通常表现为显示空

页面性能优化:preload预加载静态资源

本文主要介绍preload的使用,以及与prefetch的区别.然后会聊聊浏览器的加载优先级. preload 提供了一种声明式的命令,让浏览器提前加载指定资源(加载后并不执行),在需要执行的时候再执行.提供的好处主要是 将加载和执行分离开,可不阻塞渲染和 document 的 onload 事件 提前加载指定资源,不再出现依赖的font字体隔了一段时间才刷出 如何使用 preload 使用 link 标签创建 <!-- 使用 link 标签静态标记需要预加载的资源 --><link r