渐进式的脚本加载

标签: WEB优化 性能优化 | 发表时间:2011-01-25 23:13 | 作者:admin aoao
出处:http://varnow.org

    通过之前几篇性能指标分析系列的文章可以发现,无论是对于哪个性能指标来说,脚本的影响都是最大的。实际的线上监控数据(图1)也确实能够论证这一点,例如某个页面DOM Ready的时间在4.1s左右,而外链脚本的加载和执行则消耗了2.8s左右,比例高达68.74%。也就是说假如该页面没有脚本的话,页面的DOM Ready时间将会大大缩短。实际的页面中,脚本在加强和提高交互体验方面又是不可或缺的,因此需要从脚本的合理使用方式着手来改善脚本的使用对整体页面性能的影响。

image

    按照Javascript的加载方式大概可以分为即时加载和动态加载两类,即时加载指的是在页面中直接使用<script>标签引入资源,随着页面的解析而引入的;动态加载则是指使用除即时加载之外的方式,例如创建<script> DOM结点载入脚本。此外,引入脚本的时机也是不同的,不同时机引入脚本对性能的影响也是迥异的。根据引入脚本的方式以及时机,本文将脚本的引入分为以下几个阶段:即时加载、解析进行时动态加载、解析完成时动态加载、页面完成时动态加载、按需加载。通过调整页面中脚本在不同阶段的分布可以达到优化性能的目的。

即时加载(Page Parsing Load)

    即时加载指的是在页面加载解析的过程中使用<script>标签直接加载的脚本(包括document.write方式),例如在页面头部、或其他位置直接加载的脚本,而不是在DOM Ready之时或者更晚再加载。

    即时加载脚本对页面性能的影响如下:

    (1) 即时加载脚本会阻塞其他资源加载,而且在IE6下,多个脚本之间只能串行加载。即使是使用document.write方式也只是解决了脚本间的并行下载,依然会阻塞其他资源的加载;

    (2) 在加载、解析和执行的过程中,整个页面的渲染、解析和交互状态会被“冻结”,即使是使用document.write方式;

    (3) 通过《从用户体验出发的性能指标分析-DOM Ready》一文的分析可以得出,即时加载的脚本对DOM Ready指标的影响是非常大的,它会显著的推迟DOM Ready,从而影响其他在DOM Ready中初始化的交互功能;

    鉴于即使加载脚本对性能影响之巨大,在使用这种方式应该牢记以下原则:

    即时加载的脚本数应该尽可能的少,需要使用这种方式加载的脚本应该是页面中的核心脚本,为其他脚本所依赖,例如核心脚本库。

解析进行时动态加载(Page Parsing Dynamic Load)

    解析进行时动态加载指的是在解析的过程中即可触发加载,但是又不是直接使用<script>标签进行加载的方式,常用的方式有DOM Element-即动态创建<script>标签,还有iFramed JS-即在iframe中引入脚本,此外还有其他的方式,Steve在《Loading Scripts Without Blocking》一文中有很好的总结。

    与即时加载相比,该方式的优势在于:

    (1) 动态加载的方式属于无阻塞加载,脚本在加载的过程中不会阻塞其他资源的加载(包括其他脚本),可以充分的并行加载,有利于提高整体性能;

    (2) 动态加载的脚本在加载的过程中不会阻塞页面的渲染和交互;

    (3) 动态加载的脚本在加载的过程中不会阻塞浏览器的解析,因此脚本对DOM Ready指标的影响也减少了,使DOM Ready能够更早的触发;

    不过,该方式也存在一些问题,例如脚本如果在DOM Ready前加载完成,则在执行的时候依然会“冻结”整个页面的解析、渲染和交互。

    权衡利弊,使用该方式加载的脚本应该符合以下原则:

    应该属于核心功能,而且相关的脚本需要在页面解析的过程中即开始初始化和事件注册,否则用户将无法交互。

    在实际的优化过程中,应该尽可能的将即时加载的脚本挪到该方式下加载,不过出于对以上提到的问题的考虑,非核心功能的脚本则建议挪到下一个阶段。

解析完成时动态加载(DOM Ready Load)

    解析完成时加载本指的是在页面解析完成后即DOM Ready事件触发的时候加载的脚本。DOM Ready事件触发时,通常整体页面基本渲染完成了,因此在此时加载脚本有以下优势:

    (1) 由于是在页面解析渲染完成后加载的脚本,因此脚本的执行不会影响页面的渲染;

    (2) 在加载时机上,与前一阶段相比还不至于太晚而影响用户体验;与后一阶段-页面加载完成时加载相比,则又要提前一些;

    使用该方式加载的脚本应该符合以下条件:

    脚本属于非核心功能模块,而且脚本对于功能本身而言是增强型的而不是完全的依赖,即脚本的延迟加载不会导致功能完全不可用。例如对于非核心功能的用户输入模块,验证相关的脚本就符合这类条件,可以采用这种加载方式。

页面完成时加载(Page Completed Load)

    页面完成时加载指的是在页面完全加载完成后(包括图片、iFrame等资源)加载的脚本,或者可以说是在window的onload事件触发时进行加载。在该阶段加载脚本的优势如下:

    (1) 整个页面的所有资源加载完成,因此在此阶段加载的脚本对页面没有任何性能影响;

    (2) 如《从用户体验出发的性能指标分析-Page Load》中提到的,在Page Load后加载资源,在某些浏览器中可以让资源的加载过程对用户透明,优化用户的感官体验;

    但是由于window的onload事件的触发是由最晚加载的资源的时间所决定的,因此进入该阶段的时间是不稳定和不可控的,因此在本阶段载入的脚本应该如下要求:

   (1) 与首次加载功能无关的脚本(如某些用户操作后才会使用的脚本)或者与用户交互无关的脚本(如统计脚本);

    (2) 下一个阶段-按需加载中的脚本需要进行预加载的脚本,预加载可以改善网速较慢用户的体验,不至于需要的时候却要等待过长的时间;

按需加载(On-Demand Load)

    按需加载,顾名思义指的是当用户触发了某个功能时才加载对应的功能,使用这种方式时需要合理选择脚本加载触发点。

    按需加载的最大优势在于减少了不必要的资源请求。但是按需加载本身如果使用不当也会影响用户体验,因为加载的时机在用户执行某个操作之后,如果用户的网速比较慢的话,加载脚本可能需要等候较长的时间,而用户则不得不为此付出代价。因此,如果要使用按需加载则需要选择正确的脚本加载时机。例如对于一些提交数据的操作,可以在用户开始填写数据的时候即开始加载脚本,而不需要等到用户填写完成真正提交时才开始加载脚本。

    此外,解决体验问题的另一个方式是将脚本的加载挪到上一个阶段中进行。

总结

    脚本的加载可以分为即时加载、解析进行时动态加载、解析完成时动态加载、页面完成时动态加载、按需加载几个阶段,优化的目标是让每一个脚本找到它应该属于的加载阶段,从而达到性能和体验的平衡。优化的原则就是尽一切努力减少即时加载,将即时加载统统分散到其后的几个阶段中加载。

    与时间管理的“四象限”法则类似,以上的几个阶段实际上也可以概括为四个象限:

    第一象限 - 即时加载

    第二象限 - 解析进行时动态加载

    第三象限 - 解析完成时动态加载

    第四象限 - 页面完成时加载以及按需加载

    优化的目标即时减少第一象限中的脚本数,尽可能的将脚本放在第二象限,而一些不太重要的脚本则放到第三、四象限中。

相关 [脚本 加载] 推荐:

渐进式的脚本加载

- aoao - Miller
    通过之前几篇性能指标分析系列的文章可以发现,无论是对于哪个性能指标来说,脚本的影响都是最大的. 实际的线上监控数据(图1)也确实能够论证这一点,例如某个页面DOM Ready的时间在4.1s左右,而外链脚本的加载和执行则消耗了2.8s左右,比例高达68.74%. 也就是说假如该页面没有脚本的话,页面的DOM Ready时间将会大大缩短.

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

- - 博客 - 伯乐在线
下面的图片是我使用firefox和chrome浏览百度首页时候记录的http请求. 在浏览百度首页前我都将浏览器的缓存全部清理掉,让这个场景最接近第一次访问百度首页的情景. 在firefox的请求瀑布图里有个表现非常之明显:就是javascript文件下载完毕后,有一段时间是没有网络请求被处理的,这段时间过后http请求才会接着执行,这段空闲时间就是所谓的http请求被阻塞.

mysql backup 脚本

- - ITeye博客
网上备份脚本很多,但考虑都不周全. 保证创建备份文件只能是创建者跟root可以访问,其他用户没有权限,保证了数据库备份的安全. 上面脚本是负责备份的份数管理,. 已有 0 人发表留言,猛击->> 这里<<-参与讨论. —软件人才免语言低担保 赴美带薪读研.

RMAN 备份脚本

- - CSDN博客数据库推荐文章
RMAN冷备份、一致性备份脚本. RMAN热备份、非一致性备份脚本. rman名称不允许重复,%U肯定不重复. %D 位于该月中的第几天 (DD). %M 位于该年中的第几月 (MM). %F 一个基于DBID 唯一的名称,这个格式的形式为c-IIIIIIIIII-YYYYMMDD-QQ,. %d 数据库名称其中IIIIIIIIII 为该数据库的DBID,YYYYMMDD 为日期,QQ 是一个1-256 的序列.

CSS 溢出检测脚本

- Public - 陈成的博客
按我的理解,CSS Bug 包含:. 内容 Bug (即运营填入内容或数据库读取内容后出现的 Bug). 其中兼容性 Bug 通常在开发阶段就能解决,而内容 Bug 通常被我们忽略. 比如忘记对文字设置 overflow: hidden;比如忘记对图片设置宽高;等. 所以,为自动化这块的测试工作,我写了个 简单的脚本 ,功能有二:.

在脚本中使用 trap

- jiaosq - IBM developerWorks 中国 : 文档库
要使脚本具有合理的健壮性,需要满足的条件之一就是能够清除强制终止后留下的任何临时日志或进程. 另一项需要考虑的因素是,在收到来自用户的中断后,应当采取哪些相应措施. 通过使用 shell 内置 trap 命令和记录器 (logger) 工具,这些工具有助于提高脚本在被强制终止时的健壮性. 在本文中,我将演示使用 trap 和记录器的方法.

Javascipt脚本调试(Javascript debugging)

- - 博客园_首页
根据 CNZZ数据中心对国内主流浏览器的统计分析,2012年3月国产浏览器中360安全浏览器、搜狗高速浏览器和傲游浏览器的使用率分别为24.39%、7.37%、1.75%;国外浏览器中微软IE浏览器、谷歌Chrome浏览器及苹果Safari浏览器的使用率分别为53.40%、3.21%、2.22%.

Linux下自动FTP脚本

- - ITeye博客
前面写了一个Windows下自动FTP的脚本:. 今天新增Linux下的简单脚本,还待优化. 已有 0 人发表留言,猛击->> 这里<<-参与讨论. —软件人才免语言低担保 赴美带薪读研.

进程监控脚本

- - CSDN博客架构设计推荐文章
# 如果不存在, 就重启他. 作者:ahyswang 发表于2014-10-11 22:34:45 原文链接. 阅读:111 评论:0 查看评论.

服务监控脚本

- - Linux - 操作系统 - ITeye博客
已有 0 人发表留言,猛击->> 这里<<-参与讨论. —软件人才免语言低担保 赴美带薪读研.