关于网站加速的35条法则(来自Yahoo)

标签: web | 发表时间:2014-11-16 17:10 | 作者:spacewander
出处:http://segmentfault.com/blogs

原文见此: https://developer.yahoo.com/performance/rules.html

注意,不是翻译,只是谈谈本人的读后感。

另外注意,该文比较旧,大概是2010年的产物,所以里面会有些跟不上时代的内容。

1. 减少HTTP请求

一个典型的http请求报文大概是这样的:

  GET /3.3.0/build/yui/yui-min.js 
HTTP/1.1Host: yui-s.yahooapis.com
Pragma: no-cache
Cache-Control: no-cache...

虽然也就几行文字,但是考虑到http协议里,对同一个域名同时发出的请求是受限的 [1],如果请求太多,说不定它们会堵塞在队列中呢。哦,对了,忘记把cookie算上去了,每次请求的时候都会附带当前域下的cookie,有时候关这一项就有几百B呢。

解决方法:

  1. 文件打包使用 CSS Sprites: 将小图标们合并成一幅大背景图,再通过恰当地设置 background-imagebackground-position来取出。根据你所用的语言和框架,一般都能找到相关的工具来完成这一任务。除了可以打包图片,还可以打包css文件和js文件。把多个相关js文件和css文件打包成单一的js文件或css文件,省下的http请求数量。这也可以交由工具去做。比如Flask可以使用 Flask-Assets

  2. 内联图片可以用 data: URL模式来内联图片。比如Github 404页面上的几幅图片: https://github.com/404

2. 使用CDN

据原文的数据,对于最终用户,80-90%的响应时间都消耗在下载页面的各种组件(js、css、flash等等)中。所以加速网站响应时间,就得加速各种静态资源的下载。要想让用户尽快下载到静态资源,根据物理法则,就要把它们放到离用户最近的地方。这时候,CDN就有用武之地了。

什么是 CDN

简单说,就是通过用户就近性(IP地址)和服务器负载的判断,CDN会让用户从离他们最近的内容服务器中下载所需的静态资源。据原文数据,Yahoo将静态文件迁徙到CDN之后,响应速度加快了20%以上。当然对于一般厂商而言,不可能在全国各地自建CDN机房,这时就需要购买第三方的CDN服务了。

3. 在响应报文添加Expire和Cache-Control

Expire和Cache-Control的介绍见这里: http://www.path8.net/tn/archives/2745
这是设置浏览器缓存用的。注意,如果你设置了较长时间的缓存,那么每次修改组件内容时,也需要一并修改组件名字,否则浏览器不会重新发起请求。这就是为什么我们看到的许多js和css文件都带着hash戳或者时间戳。

4. 用Gzip压缩组件

什么是 Gzip

从HTTP/1.1开始,如果客户端支持压缩,会在在HTTP请求中添加 Accept-Encoding: gzip, deflate,服务器就能够据此返回压缩后的数据。(并在响应报文中设定 Content-Encoding: gzip)压缩后的数据可以减少多达70%现在就打开你的浏览器的开发者工具,查看响应报文,你会看到你所浏览的网页是经过gzip压缩的。而且毫无解压上的延迟,对吧?你可以gzip一切,除了图片和pdf,因为这些文件一般都是压缩过了的,使用gzip甚至可能会增大文件大小。

5. 把css文件链接放在顶部

不解释,这是html的规范了。

Unlike A, it may only appear in the HEAD section of a document, although it may appear any number of times [2]

6. 把js文件链接放在底部

道理基本上是众人皆知。因为js文件下载后,就会被浏览器执行,同时页面的渲染会被阻塞掉。要知道,等到页面中链接的js文件、js文件中引用的其他js文件都执行完才渲染页面,用户可能已经不耐烦地按下F5了。

你也可以看下script元素的 defer属性。

7. 避免使用css表达式

这种东西已经不存在了。

8. 外链js和css文件

第一条规则说到,我们应该尽量减少js和css文件个数来减少HTTP请求,那么减少到多少才是合适呢?取个极端情况,能不能完全把js和css代码内联到html文件中?

减少js和css文件数,需要注意一种情况。假如有些js和css文件经常改变,那么把它们合并在一起,会导致整个文件的改变,以及浏览器缓存的失效。所以更好的做法是,规划静态资源文件,把相对不变的合并在一起,把频繁变易的分隔开。

9. 减少DNS查找

每次访问互联网上的一个主机,假如没有命中DNS缓存,就会发起一次DNS查询,会消耗掉一定时间。如果把资源文件分布在不同的主机中,就会增加DNS缓存不命中次数,不过这又跟前面的几天规则相违背,所以还是需要权衡啊。当然如果贵司足够霸气,可以考虑下面这个方案: 全局精确流量调度新思路-HttpDNS服务详解

10. 压缩js和css文件

不解释。

11. 避免重定向

该用的时候还是得用。

12. 移除重复的script

13. 配置ETag

后端可以在响应报文中添加Etag这一项,那么当浏览器下次请求同样的资源时,会携带If-None-Match条目。假如Etag没有发生变化,服务器可以返回 304 Not Modified状态码,无须重新下载资源。

例如:

响应报文:

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

下一次的请求报文 :

    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

这件事一般交由你用的服务器(比如 Nginx)去做

14. 缓存Ajax

使用前面讲到的技术,如expire、cache-control、etag等,让浏览器将Ajax返回的结果也缓存起来。

15. 提前返回后端生成的内容

在后端的html页面完全渲染完之前,先返回部分内容。文中以PHP作为一个例子:

    ...<!-- css, js -->     
  </head>    
  <?php flush(); ?>     
  <body>       
  ... <!-- content -->

调用php的 flush函数来“冲刷”后端缓冲区中的内容。貌似是先返回head中的内容,让浏览器加载css文件,具体得由懂php的人来解释下……
这个要取决于你用的框架和语言是否允许这么做

16. 在Ajax请求中使用GET方法

因为在浏览器的实现中,GET方法耗时更短。
不过这得看业务逻辑的,对不对?

17. 延迟加载

如果可能,直到需要用时才加载某些图片、js文件……这方面有很多可用的库,比如 echo.js

18. 预先加载

呃,看待事物果然不能太绝对……这里的预先加载,是说在浏览器空闲的时候,预先加载用户接下来要浏览的内容。文中举了Google首页中的css sprite作为例子。虽然首页用不上这个sprite,但是考虑到用户基本不会停留在Google首页,而且首页内容较少,于是预先加载了这个sprite

19. 减少DOM元素数量

过多的DOM元素会拖慢js执行的数目。特别是有些页面,使用div层层嵌套。原文强调尽量少用额外添加div的方式来实现某种效果,要考虑到html的语义。

运行 document.getElementsByTagName('*').length看下当前页面有多少个DOM元素,跟优秀的同类页面比较下。

20. 将不同的内容分到不同的域名下

理由见规则1
同时注意规则9的影响,不要分得太多。

21. 最小化iframe的数目

<iframe> 好处都有啥:
* 加载第三方内容
* 作为沙盒
* 并行下载脚本
* 加载那些通用的内容(但是又不打算改为单页应用)

<iframe> 的坏处呢:
* 花销
* 阻塞页面加载
* 语义丢失

22. 减少404

对静态资源的请求,避免返回404

23. 减少cookie大小

消除无用的cookie
尽量最小化cookie的大小
恰当地设置cookie的作用域,以免影响其他子域名
恰当地设置cookie的过期时间(如果不设置的话,一旦浏览器关闭,cookie就会失效。所以无关紧要的cookie就不要设置过期时间了)

24. 给静态资源分配一个无cookie的域名

一般情况下,请求静态资源是不需要带cookie的,所以把它们独立开来。参见规则1

25. 减少js对DOM的访问Minimize DOM Access

三种方法:
1. 缓存DOM元素的引用
2. 批处理对DOM的修改,而不是每次都调用DOM方法(stackoverflow上有一个相关的回答: http://stackoverflow.com/questions/14291811/minimize-dom-access-inorder-to-have-a-more-responsive-page
3. 避免使用js来解决布局上的问题

26. 更明智地使用事件监听器

假如你在一个div下有十个按钮,可以只在那个div上添加事件监听(再通过Event参数分清来源),因为事件会冒泡的。
又比如监听DOMContentLoaded事件而不是Load事件。

27. 使用 <link>而不是 @import

这篇文章:
高性能网站设计:不要使用@import
已经交代了一切。
又可以黑IE了。

28. 避免用AlphaImageLoader

Yet another历史问题。现在无须担心这个了。

29. 优化图片

其实除了在js和css文件上动刀子,我们也可以优化图片。
文中提到了用PNG代替GIF(所以说里面的内容已经有点老了)
还推荐一些工具,如imagepicker、pngcrush、jpegtran。
总之,去除多余的图像信息,如果允许,可以牺牲下图片质量。

30. 优化CSS Sprites

将小图片水平排放而不是竖直排放。
减少图片间的间隔。
使用上述的优化图片的方式。

31. 不要在HTML中设置图片

不要使用过大的图片,然后在HTML里给它设置一个合适的(更小的)尺寸。

32. 让favicon.ico小而易于缓存

favicon.ico应该小于1k。可以考虑给它设置一个Expire报头,如果你有打算修改它的话,毕竟你不能改变它的命名。

33. 让组件小于25K

之所以要小于25K这个Magic Number,是因为iPhone不会缓存大于25K的组件。意味着如果有的文件大于25K,每次访问时都需要重新获取。

不过考虑到本文内容较老,我还是搜索求证下,最后找到了这个网址:
http://www.slideshare.net/cafenoirdesign/the-future-is-mobile-11719438 (需梯子)

Double image dimensions, then resize✤ Individual component caching: iOS 3.x will only cache HTML pages under 25k , iOS 4 102.4 kb per item✤ Total component caching: Android and iOS 4 set limit at 2MB✤ gzip has no effect on cache-ability on any device

简单说,25K限制是iOS 3时代的产物,对于现在的移动端,基本上不需要担心组件太大而无法缓存的问题(不过用户会比你更在意流量耗费的问题)。

34. 将组件打包成multipart类型

指定Content-Type为multipart,然后在一个响应报文中发布多段数据……呃,基本上没什么会用吧,太过于复杂而且效果不显著。

35. <img>避免空的src属性

这种情况有两种版本:

  <!-- html -->
<img src="">
  // javascript
var img = new Image();
img.src = "";

都会导致额外的、徒劳无功的请求。

同理,以下代码也有同样的问题:

  <script src="">
<link href="">

不过在HTML5中规定,只有合法的URL引用才会产生新的请求,所以如今类似这样的空属性不应该会带来额外的负担。

相关 [网站 加速 法则] 推荐:

关于网站加速的35条法则(来自Yahoo)

- - SegmentFault 最新的文章
原文见此: https://developer.yahoo.com/performance/rules.html. 注意,不是翻译,只是谈谈本人的读后感. 另外注意,该文比较旧,大概是2010年的产物,所以里面会有些跟不上时代的内容. 一个典型的http请求报文大概是这样的:. 虽然也就几行文字,但是考虑到http协议里,对同一个域名同时发出的请求是受限的 [1],如果请求太多,说不定它们会堵塞在队列中呢.

Webluker:为中小网站提供轻量级CDN 加速服务

- 午夜瞎想 - 36氪
对于任何网站来说,访问速度都是一个非常重要的参数. 如果你的网站加载了很久还是没有打开,那么一部分“不耐心”的用户就可能会离去了. 除了通过提升服务器性能之外,使用CDN 其实是一个提升网站访问速度的便捷方式. 不过对于中小网站来说,类似ChinaCache 的大型CDN 使用起来门槛非常的高,有没有一个轻量级容易使用的CDN 服务呢.

杨建:网站加速--服务器编写篇(上)

- cgeek - Berkeley DB - 杨建的BLOG
Nginx是我见过的Web Server中性能比较高的一个,他几乎是和我的server同时诞生,可能还更早些,框架很不错,我觉得目前版本稍微优化下,支持10w connections不成问题. lighttpd也不错,我对他的认识还是停留在几年前的性能测试上,它的性能会比nginx逊色一些. 他们都支持epoll,sendfile,可以起多个进程worker,worker内部使用非阻塞,这是比较优良的I/O的模型.

利用一点机器学习来加速你的网站

- - IT瘾-bigdata
在生活中,我有 73% 的时间在考虑 web 性能-在低配手机上达到 60 FPS、 有序加载资源、离线缓存任何能缓存的资源. 最近,我发现自己对 web 性能的定义可能太狭隘了,从用户的角度上来说,这些只是 web 性能中的一些小插曲. 所以我打开了我经常去的网站,尝试了所有的用户可能的操作,并记录操作所花费的时间.

浏览英文网站的加速器 有道网页翻译2.0发布

- 车东 - 津津乐道 有道官方博客
你还记得做阅读理解题,碰到不认识的难词、生词时是怎么解决的吗. 你还记得阅读专业文献时看到难词、生词是怎么克服的吗. 可能你和我们想到了一起,那时候,我们拿起笔,把从词典上查到的难词释义用小字标注在卷子或是文献的空白处. 现在,我们常常在电脑上浏览英文网页,获取英文信息,当然也时常遇到难词和生词. 长难词,依然是获取英文信息的拦路虎,特别是在浏览器上,无法给难词标注中文释义,可能看到后面就忘了之前查询的难词是什么意思,使得浏览英文网页的速度大大变慢,十分不方便.

Google 发布Page Speed Service,为第三方网站提供网页加速服务

- pippo - ITeye资讯频道
     Google曾经推出过Page Speed浏览器测速扩展,以及Page Spped Online API来帮助开发者提供具体的建议,好让他们的网站打开得更快. 去年Google还发布了Apache的mod_pagespeed模块,自动重写网页进行提速. 今天Page Speed又有了新成员:Page Speed Service.

谷奥: Google 发布 Page Speed Service 为第三方网站提供网页加速服务

- 郑小东 - 谷奥聚合——谷奥主站+谷安 aggregator
Google曾经推出过Page Speed浏览器测速扩展,以及Page Spped Online API来帮助开发者提供具体的建议,好让他们的网站打开得更快. 去年Google还发布了Apache的mod_pagespeed模块,自动重写网页进行提速. 今天Page Speed又有了新成员:Page Speed Service.

Google推出免费的【页面加速服务】,让你的网站越来越快

- Jack - 36氪
Google可以帮你做到,而且免费. Google刚刚推出了一个免费页面加速服务(Page Speed Service),不仅可以让你使用Google的代理服务器,而且还可以帮你优化网站代码. 你只需把网站的DNS指向Google的DNS,然后该服务就会自动抓取你的页面,然后根据最佳惯例进行优化,并通过Google的缓存代理网络向全世界提供网页访问服务.

手机网站开发及手机中图片加速显示img的Canvas方法

- - CSDN博客Web前端推荐文章
    随着手机开发越来越流行,手机开发的很多框架也应运而生,比较好用的手机网站开发框架推荐如下:.     1、zeptojs,里面封装了很多手机特有方法,例如touch.js等等. 和jquery用法差不多,很好上手. API地址:http://zeptojs.com/#$.extend.     2、jquerymobile   演示地址:http://jquerymobile.com/.