昨天接触到这篇文章《Best Practices for Speeding Up Your Web Site》,觉得太经典了,自己不由自主的想要翻译过来,鉴于本人的英语水平,只翻译了其中的某些条目,有错误在所难免。更多的还是推荐浏览原文。
首先的说明的是:优化页面显示速度,就是不管HTML内容多与少,都要尽量在最快的速度显示出来,这就是Front-end engineers首要明确的意图。所以下面所提及的优化方式,都是从这一目的出发的。下面的翻译的一些条目:
1.最小化HTTP request请求。因为一个页面显示所花费的时间很多都是花费在scripts,stylesheets,images,flashs等等,这些都会通过http request来加载,这些大概占用了页面加载时间的70%-80%,因此,减少HTTP request能很大的优化页面的加载速度。
2.使用第三方的代理服务器来加载scripts,stylesheets等等,这能降低本主服务器的负载,比如google ajax api提供的目前流行的js库:jquery,extjs,prototype,MooTools等等
3.在头部声明cache的expire。在用户第一次view页面的时候会加载全部的内容,包括html以及scripts,stylesheets,images等等,设置了cache的expire一方面能使得用户在下次view页面的时候能从缓存里读取一些数据,减少了HTTP Request的请求数,加快页面的显示。不过这要看用户view页面的回头率是否频繁。设置了cache的expire也要适当。一方面能加快加载速度,另一方面也有助于在cache的expire过期的时候使得用户获得页面的最新数据信息。
4.使用压缩技术(Gzip Components)。原理就是将scripts,stylesheet,images,flash等等压缩为一个zip文件,之后把这个zip文件链接进页面中来减少http request回调来加快页面的加载速度。通过摄自豪HTTP header的Accept-Encoding为gzip, deflate,之后在Response header里设置Content-Encoding: gzip来解压压缩包的文件,就可以将这些文件导入到页面的相应的部分。不过,如果页面中的Component比较少或者也是相对于非常小的话,还是不建议使用这种方法,还是使用普通的通过各自的连入方式加载Component。
5.将全部的Stylesheets放到head里来加载。Yahoo测试了这种方式证明了这一方式确实能加快页面的加载速度,“This is because putting stylesheets in the HEAD allows the page to render progressively.”。
6.将Scripts放置到Bottom(底部)。我们都知道,通过script标签引入文件会阻止下面的HTML内容的加载,等待script加载文件完成才加载下面的内容。因此:HTTP/1.1 specification建议在每一个主机名下不要超过两个Component同时下载。还有一点要说明的是:当script正在加载的时候,浏览器机会停止一切其他的加载项,甚至不同的主机下的文件都不会加载(通过iframe加载的内容)。
但是有时候有很难将scripts都放到bottom里,这里的主要问题就是通过document.write来添加页面内容以及作用域问题。因此,就需要使用其他的方式来解决这样的问题了。
这里有一种建议方案:就是使用deferred scripts(延迟执行scripts),通过使用script标签的defer属性来延迟执行不包含document.write的js代码。defer的机制就是先加载好scripts,之后在DOM加载完成之后,执行js代码(defer的延迟要比window.onload早),因此使用defer会在DOM加载完成,window.onload之前执行js代码。但是defer属性目前只有IE支持,Firefox等浏览器不支持,要通过检查DOM是否加载完成这样的方式来解决。因此,如果一个script可以defer延迟的话,同样也就可以把它放置到bottom里,这样就能加快页面的加载(显示)速度。
7.避免使用css的Expressions。CSS的expression虽然很强大,能动态修改css的样式规则,只有IE能识别expression属性。
但是,致命的问题在于:它执行的非常的频繁,页面的一个render,resize和scroll,以及用户的一些简单的鼠标操作,比如:移动鼠标等等都会触发expression的重复执行。一个测试表明:在页面内移动鼠标就非常容易的产生超过10000次的执行次数。这将是难以想象的耗费性能。
一种解决办法就是一次执行expression之后,就给css 样式指定确切的值,而不在需要依赖expression。
8.通过外联的方式来加载外部的Javascript和css到页面里。在第一条里我们谈到减少Http request请求来加载Component,而这里又提倡使用外联的方式来加载scripts、Stylesheet等等Component,不是冲突了吗?这里来解释一下:如果不是通过外联的方式来加载文件,这样在每次加载页面的时候,都需要去加载内联的Javascript和css内容,这就使得HTML容量变大了。而使用外联的方式的好处在于浏览器会缓存这些文件,第二次加载页面的时候就会在缓存里读取这些文件(如果缓存里还没有清除的话),这使得HTML页面“变小”了,不是更快加载HTML了吗。从这一角度来考虑,视具体情况而定,来综合考虑上面所提到的几种优化方案。
9.压缩Javascript和css代码。压缩代码就是清除掉一些不需要的characters,减小代码文件的大小,从而加快加载。可以通过使用JSMin或者YUI Compressor,还有Jspacker等等压缩工具。压缩代码的范围可以很广泛,包括独立的js或者css文件,当然也可以是内联的js或者css代码(google就使用了这种方式),也可以是上面所说的通过压缩Components联入页面的各个js或者css文件。
10.删除重复的Scripts Component。有时候如果不加注意,可能就会重复加载了同一个script联入文件,比如通过script联入,之后在某种形式下使用php的insertScript又联入了同一个文件,这都是有可能的。这将会有哪些不合理呢:一个是花费Http request的数目而且还会影响浏览器的缓存方面的问题,使得script重复加载。
11.使Ajax可以缓存。Ajax在我们看来是用于跟服务器异步传输数据的,每一步都需要新的数据。当然这是我们都计较长涉及到的,但是某些情况下,Ajax缓存同样重要,说个比较简单的例子:比如用户通过搜索(当然这个搜索是通过Ajax形式)来观看一些书籍的内容的时候,因为书籍内容是分章节分页面的,而且内容都基本会保持不变,当用户搜索同一文章而且Last modified没有修改的情况下,就可以从缓存里返回上次的搜索内容,而不必重新搜索,从后台传输数据了。
12.在Ajax Requests中使用GET方式。Yahoo!Mail团队发现当使用XMLHttpRequest的时候,使用POST方式在浏览器会执行两部操作:先发送headers信息,之后发送data数据。而GET方式只需要“take one TCP packet”。但是IE中对于URL长度的限制在2K之内,所以data超过2K的话还是需要使用POST的方式。
13.延迟加载一些Components。我的理解是这样的:对于页面中一些不需要在页面中即刻需要显示出来的效果或者内容的时候,可以延迟加载这些内容。比如Javascript中的拖动以及一些暂时隐藏的内容等等,这些都可以在页面其他的内容加载完之后再去加载它。这就不会影响整体的页面的显示速度了。
14.预先加载Components。这似乎跟上面的延迟加载Components有冲突,但是不尽然。这里的情况是这样的:在浏览器空闲的时候(比如:onload之后)预先加载Components(images,scripts,Stylesheets),这样在用户浏览其他页面的时候,当其他页面中使用到了这些Components的时候,就可以直接在Cache里读取,而无需重新加载。
15.减少DOM Elements。这就涉及到HTML页面的架构问题了,可以想象,当一个页面中存在500或者5000个DOM Elements的时候,在页面加载的时候,DOM渲染速度,将会是一个怎样的区别。所以,这也要求设计HTML页面架构的时候能保持简洁和语意化。使得DOM Elements尽量的少,提高DOM渲染速度。
16.减少页面中的iframes数量。我们知道,iframe可以将其他页面嵌入到当前页面中。但是懂得它的运行方式将会非常有用。
好处是:是一个安全的沙箱;可以平行的下载scripts;减缓第三方内容的显示比如广告等。
坏处是:花费时间来加载页面内容如果链接到一个空页面或者一个不存在的页面;打断了页面的onload进程。
17.避免404错误的出现。404错误是没有找到指定URL的页面,出现这个错误页面的时候也是很耗费时间的,而且它很糟的一个方面是当用户等待了几秒甚至更长的时间来等待页面显示,最后显示出来的是404错误,用户体验度明显下降了。还有一个很糟的方面是如果通过script外联的Javascript文件找不到,这一方面会打断页面的加载进程,另一方面也使得页面的功能逻辑缺失。
18.减小Cookie的大小。HTTP cookies在存储一下私人信息等方面,但是Cookie是通过HTTP headers在服务器端和客户端之间交换的。所以就非常有必要去尽量减小cookie的大小,使得用户的response time的影响最小化。
在“When the cookie Crumbles”一篇文章里详细分析了Cookie,它指出:
a.去除一下不需要的cookies。
b.尽量使得cookie最小化以简短用户的response time。
c.适当的设置cookie的expire过期时间。
d.在设置cookie的domain的时候要非常小心,使得其他的sub-domains不会受影响。
19.要明智的设置Event Handlers。有时候页面感觉反应迟钝或者缓慢,一个方面是因为页面中的event handlers在DOM Elements里设置的太多了,事件通过冒泡或者捕获等等导致事件发生的太频繁。要根据实际情况,明智的设置Event heandlers。
20.外联css文件选择 而不是@import。上面我们提到了将css外联文件都放置到head部分里,这样可以加快页面加载速度。对于@import语法,在IE下等同于使用 外联css文件并放置到bottom里了,所以不推荐使用@import的方式。
21.避免使用Filters。我们知道,IE下css的滤镜可以通过filter属性来设置很多华丽的效果。但问题是filter一方面打断页面的渲染和当图片在加载的时候冻结了浏览器;另一方面也是增加了内存的消耗。
所以,应该避免使用filter滤镜,使用更好的PNG8来代替,如果非要使用,请使用_filter,使得用IE7的用户能有一个更好的用户体验。
22.合理的使用各种格式的image。图片有gif,png,jpg等这三种是网页比较常用的三种格式,但是知道这三种格式的图片特性,合理的使用,也是非常有必要的。
gif一般文件都比较小,但是只有256种颜色。
png最大的一个特点就是支持透明度。
jpg以它的高清晰度而为人所用。
23.使favicon.ico尽量小并可以缓存。很多网站都设置了favicon.ico一个小图片在浏览器的URL地址栏里显示。这非常好。但是favicon.ico跟cookie以及其他的Components一样都是需要Http request加载的,所以尽量保持它能被浏览到(避免出现404错误)和可以缓存,就显得十分有必要了。下面是关于favicon.ico的两项建议:使得favicon.ico保持在1K以下;在header里合理设置Expire过期时间。
24.保持全部的Components的大小在25K以下。这个限制的原因是由于iPhone的机制:如果超过25K,它就不会缓存页面的Components。因此为了页面跟iPhone兼容,合理减小Components也是有必要的。
上面的翻译是根据自己的英语水平以及自己对于它们的一点见解,有错误的地方在所难免,本人都苦于没有中文版的介绍。所以干脆自己在浏览过后小译一番,也方便自己以后对它的理解吧。但是本人还是推荐对这方面感兴趣的朋友去阅读原文。
更多内容请浏览:《Best Practices for Speeding Up Your Web Site》,《Part 3: When the Cookie Crumbles》,《Part 2: Browser Cache Usage – Exposed!》,《http://support.microsoft.com/?id=922733》,《YUI 2: ImageLoader》,《YUI 2: Get Utility》,《Part 4: Maximizing Parallel Downloads in the Carpool Lane》,《High Performance Ajax Applications》,《Part 5: iPhone Cacheability – Making it Stick》
到超级傻的空间来了~~~ 意外