yahoo前端优化经验

已由14条增加到35条

1. 减少http请求

80%的用户等待时间消耗在前端,大部分时间花在下载页面组成,包括:图片,css,js,flash等。减少页面资源自然可以减少http请求数,下面是常用的一些方法:

  • 合并文件:包括css和js文件
  • CSS Sprites:减少图片请求,把背景图片合并成一张图片,用background-position定位相应的图片,http://www.csssprites.com/ 这是个工具网站,它可以自动将你上传的图片合并并给出对应的background-position坐标,并将结果以png和gif的格式输出。
  • Image maps:The intention of an image map is to provide an easy way of linking various parts of an image without dividing the image into separate image files,做活动页的时候我经常用这种方法,在一张大图里进行定位。
  • inline images:用data: URL 把图片数据嵌到网页里,减少了图片请求,但增加了html文档的大小,且不是所有浏览器支持,格式为
    data:[][;base64],

    例子:<img src=”data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub/ /ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcpp V0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7″ alt=”embedded folder icon” width=”16″ height=”14″ />

    Google主页搜索框右侧 话筒就是用的inline images

     

2. 减少DNS查找

DNS是神马就不多说,计算机网络都学过,好吧,就是一个hostname到ip地址的映射,一般对于根据hostname找到ip的时间为20-120ms,在DNS查找完成之前,浏览器无法下载任何内容。

减少页面中hostname的数量,可以减少DNS查找的时间,但是也限制了并行下载(下面会提到),yahoo的建议是hostname不要多于4个,这样在DNS查找时间和资源并行加载之间做了一个平衡。

 

3. 压缩js和css

去掉空格转行,对于js,替换掉长的变量名,推荐两个工具 JSMinYUI Compressor

 

4. 避免重定向

状态码为301,302的时候,下面是一个例子

 HTTP/1.1 301 Moved Permanently Location: http://example.com/newuri Content-Type: text/html 

 

经常被忽视的一个问题: url里木有写/的时候,会发生一次重定向,比如 http://www.123.com/demo会被转向到http://www.123.com/demo/

 

 

 

5. 避免重复的js文件

这个问题在团队只有一个人的时候较少发生,但随着团队人员的增加和js文件的增多,这种情况还是时有发生的

重复的js文件,不仅增加了http请求,也增加了执行js的时间

 

6. 配置实体标签

实体标签 ETags,判断浏览器缓存里的资源是否和服务器匹配的一种机制,下面是个例子

      HTTP/1.1 200 OK
      Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
      ETag: "10c24bc-4ab-457e1c1f"
      Content-Length: 12195

之后,浏览器如果要验证资源是否是最新的,使用If-None-Match header把ETag标签发回给服务器,如果ETag匹配,则返回304

      GET /i/yahoo.gif HTTP/1.1
      Host: us.yimg.com
      If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT
      If-None-Match: "10c24bc-4ab-457e1c1f"
      HTTP/1.1 304 Not Modified

在只有一台服务器的情况下,Etag用起来木有问题,但是如果用到集群,那么不同服务器上对同一资源的Etag也是不一样的,这种情况下,Etag只是增加HTTP header的大小,而无其他好处,直接去掉吧

 

7. 让Ajax可缓存

看个例子,一个Email会用ajax来动态补全用户输入的收信人,如果用户的联系人没有变过,那可以直接从缓存读取联系人数据。可以通过配置Expires或者Cache-control header来实现,我们需要告诉浏览器,什么时候要从服务器重新下载数据,一个办法是在ajax请求的url后面加上时间戳,来表示用户上次修改了联系人数据的时间。比如&t=1190241612,如果自从上次下载数据之后,联系人没有变过,那么时间戳就是一样的,数据会从缓存中读取;如果联系人变过了,url也就变了,浏览器就会从服务器请求数据。

 

8. Flush the Buffer early

额,这个不知道该肿么翻译

用户请求一个页面的时候,服务器需要200-500ms的时间生成完整的HTML页面,这段时间内,浏览器处于idle状态,因为在等待数据。在PHP里面,有个flush()函数,它允许我们把部分生成好的html返回给浏览器,这样可以在服务器生成剩下页面的时候,浏览器可以开始获取页面资源。

例子:

 ... 
    
    
    
    ... 

一般把flush放在head标签的后面,一方面是body之前的内容生成起来容易,另一方面浏览器可以先开始下载css和js文件

 

9. 用GET请求

Yahoo Mail团队发现,在用XHR的时候,POST请求在浏览器是分两阶段处理的:发送请求头,然后发送数据,而用GET只需要一个TCP packet,url最大长度是2K,因此如果发送数据大于2K,还是要用POST

 

10. Post-load Components

我理解为按需加载,延迟加载的意思。

页面第一次加载的时候,哪些是必需的,哪些不是。比如你有js代码是用来做拖曳效果的,那么这些可以延迟加载,因为页面的渲染并不需要,其他可以post-loading的包括页面中隐藏的内容,以及第一屏看不到的图片等。

常用的工具有:YUI Image Loader, YUI Get utility

 

11. Preload Components

提前加载,利用浏览器的空闲时间来加载以后可能用到的资源,这样用户在访问下一个页面的时候,大部分资源已经在缓存里了,可以大大提高下一页面的加载速度。

提前加载有下面3种类型:

  • Unconditional preload —见Google主页,有些sprite图片是首页用不到,而是搜索页要用的
  • Conditional preload — 根据用户行为预测用户下一步会去哪个页面,然后加载相应资源,在search.yahoo.com 可以看到用户在搜索框输入的时候,发生了那些资源加载
  • Anticipated preload — 在界面升级改版的时候,经常听到用户抱怨,新版炫是炫,但速度太慢了,其实原因在于,旧版本大部分资源是使用的缓存,而新版是全部重新加载的。我们可以在新版发布之前就在旧版本里提前加载一些资源,这样新版本发布的时候,用户就不回嫌速度多少慢了- –

12. 减少DOM元素

DOM太多,首先增加页面大小,其次js里的DOM操作速度会慢,所以不要滥用div

13. 把资源分散到不同域

这个方法可以并行加载资源,前面也讲过DNS查找的问题,最佳的方案是2-4个domain,比如,我们可以把html和动态内容放在www.abc.com,把静态资源放在static1.abc.com和static2.abc.com

14. 减少iframe数量

<iframe> pros:

  • Helps with slow third-party content like badges and ads
  • Security sandbox
  • Download scripts in parallel

<iframe> cons:

  • Costly even if blank
  • Blocks page onload
  • Non-semantic

15. No 404s

发了请求却获取了404 not found,这不是浪费嚒

16. 减小Cookie大小

HTTP cookie会在服务器和浏览器直接通过HTTP header交换

“When the Cookie Crumbles” 里有较多的探讨:

  • Eliminate unnecessary cookies
  • Keep cookie sizes as low as possible to minimize the impact on the user response time
  • Be mindful of setting cookies at the appropriate domain level so other sub-domains are not affected
  • Set an Expires date appropriately. An earlier Expires date or none removes the cookie sooner, improving the user response time

 

17. 对于静态资源使用无Cookie的域

浏览器请求静态资源比如图片的时候,也发送了cookie,这些cookie对于服务器来说是没用的,因此,我们要确保请求静态资源的时候不带上cookie,解决方案是用单独的域来存放静态资源。

比如,域名是www.abc.com,你可以把静态资源放在static.abc.com上。如果在主域abc.com上设置了cookie,那发送给static.abc.com的请求还是会带上cookie。对于这种情况,可以买个新的域名,用来存放静态资源。

 

18. CDN的使用

内容分发网络,从离用户最近点的节点下载数据,减少数据加载时间

19. 添加Expires或者Cache-control header

两个方面

  • 对于静态内容,设置长的过期时间
  • 对于动态内容,用合适的Cache-control header
浏览器使用缓存来减少http请求的数量和大小,web服务器用HTTP响应中的Expires header来告诉客户端,某个组件可以被缓存多久,比如:
Expires:Tue, 01 Aug 2023 23:06:30 GMT

表示可以缓存到2023年...

有同学可能要问,缓存这么久,我文件改了肿么办?用户还是用缓存,那岂不杯具了- -,嗯,方法就是改变文件名,大家可以看大型网站的css和js,很多在文件名后面加上了?t=20130808,或者加一个版本号

 

20. 减少DOM Access

js操作dom是比较慢的,我们应该:

  • Cache references to accessed elements
  • Update nodes “offline” and then add them to the tree
  • Avoid fixing layout with JavaScript

更多的点这里, “High Performance Ajax Applications”

 

21. 更高效的事件处理

当页面中有大量元素,而且每一个都要一次或多次绑定事件的时候,这种情况可能会影响性能。每绑定一个事件都是有代价的,要么是加重了页面负担,要么增加了运行期时间。

这时候可以用事件代理,在parent dom上绑定事件,根据事件target的不同,做不同的处理。

 

22.用link而不是@import

这两者都可以引入外部css文件,区别如下:

隶属上的差别

link属于XHTML标签,而@import完全是CSS提供的一种方式。link标签除了可以加载CSS外,还可以做很多其它的事情,比如定义RSS,定义rel连接属性等,@import就只能加载CSS了。此处注意浏览器的link src为空时候时会导致页面加载次数增多。

@import次数限制

传闻在IE6下,@import只能引入31次css文件,可是可以通过在css文件中再次import来垂直扩展,断桥残雪没有测试过,不过如果出现这样的情况,说明这个写代码的人也挺变态的。

加载顺序的不同

当一个页面被加载的时候(就是被浏览者浏览的时候),link引用的CSS文件会同时被加载,而@import引用的CSS 会等到页面全部被下载完再被加载。所以有时候浏览@import加载CSS的页面时开始会没有样式,然后突然样式会出现,网速慢的时候还挺明显,@import这点跟把CSS文件放在页面结尾效果相同,不过如果我们一些样式开始页面并不会出现,而是在交互时才出现的CSS样式,可以通过这个方法引入,时间上错开。例如:Ajax的html,交互时的弹出框,弹出div等

兼容性上的差别

由于@import是CSS2.1提出的,@import只有在IE5以上的才能识别,而link标签无此问题(似乎影响不大~)。
使用DOM控制样式时的差别

当使用javascript控制DOM(document.styleSheets)去改变样式的时候,只能使用link标签,因为@import不是dom可以控制的。

综上,避免用@import

 

 

 

23. 避免Filters

IE中的AlphaImageLoader用来处理ie6的png图片半透明问题,但是,这个过滤器会在下载png的时候阻塞浏览器,同时也增加了内存消耗。替代方案是使用png8(博主木有用过,先持保留态度)

 

24. 优化图片

这方面博主研究的比较少,就不翻译了,下面介绍的 imagemagick 工具,待我试用之后来发体验

  • You can check the GIFs and see if they are using a palette size corresponding to the number of colors in the image. Using imagemagick it’s easy to check using
    identify -verbose image.gif
    When you see an image using 4 colors and a 256 color “slots” in the palette, there is room for improvement.
  • Try converting GIFs to PNGs and see if there is a saving. More often than not, there is. Developers often hesitate to use PNGs due to the limited support in browsers, but this is now a thing of the past. The only real problem is alpha-transparency in true color PNGs, but then again, GIFs are not true color and don’t support variable transparency either. So anything a GIF can do, a palette PNG (PNG8) can do too (except for animations). This simple imagemagick command results in totally safe-to-use PNGs:
    convert image.gif image.png
    “All we are saying is: Give PiNG a Chance!”
  • Run pngcrush (or any other PNG optimizer tool) on all your PNGs. Example:
    pngcrush image.png -rem alla -reduce -brute result.png
  • Run jpegtran on all your JPEGs. This tool does lossless JPEG operations such as rotation and can also be used to optimize and remove comments and other useless information (such as EXIF information) from your images.
    jpegtran -copy none -optimize -perfect src.jpg dest.jpg

25. 优化CSS sprites

  • 水平排列图片,这样图片会小一些
  • 颜色相似的放在一起,最好在256色以下
  • 图片间间隔要尽可能小

26. 不要在html中缩放图片

显而易见,只需要100*100的图片,但是用500*500的图片,两个字:浪费

27. 组件在25k以下

如果考虑移动设备的话,要注意这个问题,iphone不会缓存25k以上的文件
详见: http://yuiblog.com/blog/2008/02/06/iphone-cacheability/
剩下还有几个:
28. 避免空的img src
29. Gzip压缩

30. 样式表放顶部

31. js放底部

32. 避免css表达式

33. 使用外部css和js

34. favicon.ico尽可能小且被缓存
35. Pack Components into a Multipart Document

 

 

 

 

待续…….

 

 

 

 

 

 

 

 

 参考文献

http://developer.yahoo.com/performance/rules.html

 http://www.websiteoptimization.com/speed/tweak/inline-images/

http://en.wikipedia.org/wiki/Image_map

 

2 Responses

  1. 晋文格墨说道:

    你的博客是用什么做的?wordpress?还是什么?