Even Faster Web Sites: 读书笔记(一)

《Even Faster Web Sites》是Steve Souders的新书。Steve Souders现在是Google工程师,《High Performance Web Sites》一书的作者,Google Web Ex系列讲座的主持人,对前端优化有很专业的研究。他的UA ProfilerCuzillion项目尤其引人注目。

《High Performance Web Sites》这本书相信大家都比较熟悉,Souders在其中主要讲解了Yahoo!的14条网站性能军规。很是期待这本《Even Faster Web Sites》,可惜国内市面上还没有。偶得电子版一套,迫不及待打印出来,细细读来。

这本书只有一多半是Souders写的,其他部分是Crockford, NCZ等人的贡献,因此十分有内容。这次先记一些关于页面加载性能方面的读书笔记。

Splitting the initial payload

要提高前端性能,可以这样:页面在第一次加载时,只加载渲染页面所需要的资源(主要针对js),以及一个ScriptLoader方法。其他js资源在需要的时候再动态加载。这样做的挑战就是分离用于初次渲染的js资源,也就是找到split。微软有一个Doloto项目是做这个的,但Doloto还没有向外公布,所以我们得手动搞分裂了。

Loading scripts without blocking

外部js文件在下载和执行时,大多数浏览器都会阻塞其后面的内容(ps这也是可以理解的)。要防止这种阻塞,有若干种办法。我们比较常用的大概是XHR注入和Script tag。Souders还介绍了XHR Eval, Script in Iframe, Script Defer, document.write(<script>)等,并且画出了决策树。这些方法原理都是用异步加载外部js文件,以提高页面渲染速度。方法类似于我们用script tag来实现类ajax跨域应用。

大家可以用Cuzillion来真实测试一下堵塞情形,非常有意思,非常有必要,非常好。

前两天NCZ在他的博客上也对这种异步加载作了介绍,The best way to load external JavaScript。他认为这项技术的best practice是,首先写一个scriptLoader.js,再把页面所需要的其他js都放在second.js里,把scriptLoader.js放在</body>之前,再紧跟行内js加载second.js文件。确实不错,而且YUI和Google Analytics都这么做了。

那么到底用哪种方法来做script loader呢,在实际应用中,我认为如果不需要跨域、不考虑多个js文件加载顺序的话,XHR Injection最好,因为它不会阻塞onload事件(发现TinyMCE加载插件就是这个原理);否则的话,就是用script tag方法。

Positioning inline scripts

行内js在执行时,会阻塞其后内容的并行加载、页面渲染。顺便说,如果执行时间过长(100ms以上),用户会感觉到卡,体验非常不好。为了防止阻塞,可以用setTimeout来实现异步调用。那么文档下载完之后,为了给浏览器喘息的机会(进行渲染),延时多久才让这些js执行呢,IE下0ms即可,Firefox下是250ms。

另外有一个大忌,就是外部css文件紧跟行内js的情况。这样会造成比较严重的阻塞。是什么原因呢?行内js一般不会被阻塞,除非代码前面有css。

<link rel='stylesheet' type='text/css' href='a.css' />
<script type="text/javascript">
// do a lot of things
</script>

假如行内js前有一个外部css文件(如上述代码),那么这段js要等到css文件完全下载完才会被执行,js被阻塞,造成了页面剩余内容被阻塞,恶劣的连锁反应被引发。

先总结这么多,欢迎指正!

You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

7 Comments »

 
  • clone168 says:

    您好,我是一个对web前端非常感兴趣的大学生,我最近看到射雕(lifesinger)的文章里面也谈到了页面渲染与文件加载,可是我现在有一个很疑惑的问题,希望您能帮我解答;Js、css放在页面内部和从外部引入到底对页面的加载和渲染有什么不同?而且放在页面内部的话,因为位置不同又会产生什么影响?js的外部引入用dom或者是“document.write()”与html标签“”引入为什么就不一样?

  • yongbin says:

    @clone168
    基本上是这几个要点:
    1. 对于外部资源css, image, iframe,浏览器可以并行下载,但有同域最大连接数限制(IE为2,FF默认为6)。
    2. JavaScript不管是行内的还是外部的,下载和执行,都会阻塞浏览器下载后续资源。因此对于行内js,提倡放到底部,或者用异步调用的方式来执行。
    3. 用document.write来生成script标签,可以实现多个js文件的并行下载(仅IE),但仍会阻塞其他资源。
    你可以用Cuzillion去做测试,用Firebug自己去看。

  • clone168 says:

    谢谢您的回答!

  • 拜读大作,ie8 默认貌似支持6个并发了

  • lcb says:

    文章中提到”行内js在执行时,会阻塞其后内容的并行加载、页面渲染。”
    紧接着又提到”行内js一般不会被阻塞,除非代码前面有css。”
    这不是冲突了吗?

  • yongbin says:

    不冲突啊,行内js会阻塞后面的内容,但它本身不会被阻塞,除非前面有css文件啊。

  • lcb says:

    哦,明白了

 

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>