《高性能网站建设指南》--读书笔记

在前端开发中如何提升网站性能是每个前端工程师必须所考虑的内容。通过阅读《高性能网站建设指南》加深了对提升网站性能的各种方法的认识,同时在今后的开发中也能更好的运用。

规则一、减少HTTP请求

  1. CSS Sprites合并图片,减少HTTP请求

  2. 内联图片。
    使用Data URL技术,图片数据以base64字符串格式嵌入到了页面中,减少了HTTP请求。

    • 使用场景:

      • 当图片很小时,可用dataURL,这样既可以避免HTTP请求,同时数据量也不大
      • 当图片是服务器生成且每个用户都不一样的时候,例如验证码
      • dataURL用在css文件中可避免单纯的dataURL图片不被浏览器缓存这个缺点
    • 缺点:

      • Base64编码的数据体积通常是原数据的体积4/3,也就是Data URL形式的图片会比二进制格式的图片体积大1/3。
      • Data URL形式的图片不会被浏览器缓存,这意味着每次访问这样页面时都被下载一次,不适合在网站中大量使用。
  3. 合并脚本和样式表,尽量减少js和css的请求数量

规则二、使用内容发布网络

内容发布网络(CDN)是一组分布在多个不同地理位置的Web服务器,用于更加有效地向用户发布内容。
常用的CDN有:

规则三、添加Expires

页面中都包含大量的组件,通过web服务器使用一个长久的expires头,使得这些组件可以被缓存,这样在后续页面中避免不必要的HTTP请求
缺点:要求服务器和客户端的时间严格同步,过期日期需要检查,并提供新日期
HTTP1.1引入Cache-Control头来克服Expires头的限制
cache-control使用max-age指令
max-age请求的内容过多久过期(相对于请求时间Date)失效,默认以秒为单位
具体的过期时间配置可在Apache配置文件中添加mod_expires.c配置信息。

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "now plus 1 month"
    ExpiresByType application/x-javascript "now plus 5 day"
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType image/bmp "access plus 1 month"
    ExpiresByType image/x-icon "access plus 1 month"
    ExpiresByType image/png "access plus 1 minutes"
    ExpiresByType application/x-shockwave-flash "access plus 1 month"
    ExpiresDefault "now plus 1 minutes"
</IfModule>

配置信息可参考Apache Module mod_expires

规则四、压缩组件

通过开启gzip压缩来减小HTTP响应数据包的大小
值得压缩的内容有HTML xml css js json
不该压缩的内容图片 pdf,他们在上传到服务器的时候一般就已压缩好,再压缩只会浪费CPU
通过配置Apache 2.x的mod_deflate模块

<IfModule mod_deflate.c>
    DeflateCompressionLevel 6 
    SetOutputFilter DEFLATE 
    SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary 
    SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary 
    SetEnvIfNoCase Request_URI .(?:pdf|doc)$ no-gzip dont-vary 
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/x-javascript application/json
    <IfModule mod_setenvif.c>
        BrowserMatch ^Mozilla/4 gzip-only-text/html 
        BrowserMatch ^Mozilla/4.0[678] no-gzip 
        BrowserMatch \bMSIE !no-gzip !gzip-only-text/html 
    </IfModule>
</IfModule>

配置信息可参考Apache Module mod_deflate

规则五、将样式表放在顶部

将样式表放在head标签里可以避免白屏,这样浏览器能更快的展现内容,用户体验更好
而将样式表放在底部会导致浏览器阻止内容逐步呈现,为避免当样式变化时重绘页面,浏览器会延迟显示页面中的元素

规则六、将脚本放在底部

在下载脚本时浏览器会阻塞并行下载,原因:

  1. 脚本可能会修改页面内容,因此浏览器会等待
  2. 需要保证脚本能够按照正确的顺序执行

将脚本放到页面底部,这不会阻止页面内容呈现而且页面中的可视组件能尽早下载

规则七、避免CSS表达式

表达式的问题在于对其进行的求值的频率比人们期望的要高,它们不只在页面呈现和大小改变时求值,当页面滚动、甚至用户鼠标在页面上移过时都要被求值。频繁地求值计算会导致性能底下
解决方法:

  • 避免使用css表达式
  • 若必须使用css表达式,可使用一次性表达式
  • 使用事件处理器

规则八、使用外部的JS和CSS

好处:

  1. 外部js和css文件有机会被浏览器缓存起来
  2. 外部文件可以提高页面组件的重用率

规则九、减少DNS查找

方法:

  • 通过使用Keep-Alive,重用现有连接避免重复DNS查找
  • 使用较少的域名可以减少DNS查找的数量(页面性能需要在减少DNS查找和并行下载之间权衡)

规则十、精简JavaScript和CSS

通过精简从代码中移除不必要的字符,注释,空白符等,从而达到减小请求文件大小的目的
在实际开发中一般将js和css通过工具压缩为min文件

规则十一、避免重定向

常见的重定向状态码有:

  • 301 Moved Permancently
  • 302 Moved Temporarily(Found)
  • 304 Not Modified 并不是真正的重定向,避免下载已经存在的缓存

重定向会延长从发出请求到请求资源被下载的这段时间
有一种重定向最浪费也发生的很频繁 缺少结尾的斜线
当缺少结尾的斜线时它允许自动索引(自动转到默认的index.html)并且能够获得与当前目录相关的URL
避免重定向方法

  • 通过这事Alias mod_rewrite等
  • 如果域名变了可以使用CNAME记录

规则十二、移除重复脚本

重复脚本损伤性能的两种方式

  • 带来不必要的HTTP请求
  • 执行脚本所浪费的时间

规则十三、配置或移除Etag

Etag是web服务器和浏览器用于确认缓存组件的有效性的一种机制
服务器在检测缓存的组件是否和原始服务器上的组件匹配时有两种方式:

  • 比较最新修改时间
  • 比较实体标签

最新修改日期

原始服务器通过Last-Modified响应头来返回组件的最新修改日期
当组件第一次被请求成功后浏览器缓存了该组件以及它的最新修改日期(允许缓存),当再次请求该组件时,浏览器会使用If-Modified-Since头将最新修改时间和原始服务器上该组件的最新修改时间进行比较,如果相同则返回一个304,而不传输数据,浏览器将使用缓存数据。

实体标签

ETag是唯一标识了一个组件的一个特性版本的字符串
ETag:"24-54c6a9bd53bd1"
当组件第一次被请求成功后浏览器缓存了该组件以及它的最新修改日期(允许缓存)还有ETag信息,当再次请求该组件时,浏览器会使用If-None-Match头将ETag和原始服务器上该组件的ETag进行比较,如果相同则返回一个304,而不传输数据,浏览器将使用缓存数据。

ETag带来的问题

当你使用服务器集群时,相同的组件从一台服务器带另一台服务器,Aapache和IIS产生的ETag是不同的,这样组件下载次数将增加,导致性能下降
当If-None-Match比If-Modified-Since共存时,只有If-Modified-Since和If-None-Match在完全匹配时,服务器才能返回304。否则由于If-None-Match比If-Modified-Since具有更高的优先级,ETag不同,服务器就会返回200

解决办法

  1. 配置ETag
FileEtag INode Mtime Size 
INode:文件的索引节点(inode)数  
MTime:文件的最后修改日期及时间  
Size:文件的字节数  
All:所有存在的域,等价于:FileETag INode MTime Size  
None:移除ETag

有网友建议只是用MTime和Size就好了,有待验证
2. 移除ETag
在Aapache配置文件按中添加FileETag none

规则十四、使用Ajax可缓存

如果使用ajax向服务器发起大量的GET请求则可以为其请求的资源设置长久的expires头