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

写在前面

  • 书籍介绍:本书结合Web 2.0以来Web开发领域的最新形势和特点,介绍了网站性能问题的现状、产生的原因,以及改善或解决性能问题的原则、技术技巧和最佳实践。重点关注网页的行为特征,阐释优化Ajax、CSS、JavaScript、Flash和图片处理等要素的技术,全面涵盖浏览器端性能问题的方方面面。
  • 我的简评:这本书可能有点过时,但针对网站性能优化来说,书里面提到的优化方式都是比较经典的,即使是现代浏览器和语言新特性,包括各种新的开发框架,他们的优化点和提升点都还是基于本书提到的这些规则,做项目的性能优化时,可以基于这些规则去思考、去扩展。
  • !!福利:文末有pdf书籍、笔记思维导图、随书代码打包下载地址哦

第1章 规则1 - 减少HTTP请求

  • 图片地图:多个HTTP请求减少为只有一个HTTP请求
  • CSS Sprites:将多个图片合并到一张图片上
  • 内联图片:data: xxx都是用于内联图片的
  • 合并脚本和样式表:多个脚本合并为一个脚本,多个样式表合并为一个样式表

第2章 规则2 - 使用内容发布网络

  • 内容发布网络:一组分布在多个不同地理位置的Web服务器,用于更加有效地向用户发布内容
  • 节省

第3章 规则3 - 添加Expires头

  • Expires头:告诉Web客户端可以使用一个组件的当前副本,直到指定的时间为止
  • Max-Age和mod_expires:使用max-age指定组件被缓存多久;mod_expires可以以相对的方式设置日期
  • 空缓存 VS 完整缓存:拥有完整缓存的页面浏览所占的百分比要高于拥有完整缓存的唯一用户
  • 不仅仅是图片:长久的Expires头应该包含任何不经常变化的组件,包括脚本、样式表和Flash组件
  • 修订文件名:嵌入版本号不仅可以改变文件名,还能在调试更容易地找到准确的源代码文件

第4章 规则4 - 压缩组件

  • 压缩是如何工作的:Web客户端可以通过HTTP请求中的Accept-Encoding头来标识对压缩的支持

  • 压缩什么:很多网站会压缩HTML文档。压缩脚本和样式表也是非常值得的

  • 节省:压缩通常能将响应的数据量减少将近70%

  • 配置:Apache1.3使用mod_gzip而Apache2.x使用mod_deflate

  • 代理缓存:Web服务器的响应中添加Vary头。Web服务器可以告诉代理根据一个或多个请求头来改变缓存的响应

  • 边缘情形:发送压缩内容到不支持它的客户端、忘记将压缩内容声明为已经进行了gzip编码等,页面会被破坏;当mod_gzip检测到你在使用浏览器白名单时,会自动将User-Agent字段添加到Vary头

  • 压缩的实际效果:压缩通常能将内容压缩约70%,但这会随着空白及重复字符的数量而变

第5章 规则5 - 将样式表放在顶部

  • 逐步呈现:将样式表放在文档底部会导致在浏览器中阻止内容逐步呈现
  • sleep.cgi:放大组件的响应时间,使得可以形象的看到它们在页面加载和响应时间上的效果
  • 白屏:在IE中,将样式表放在文档底部会导致白屏问题的情形有以下几种:在新窗口中打开时,重新加载时,作为主页
  • 无样式内容的闪烁:在所有样式表加载并解析完毕之前无需绘制任何东西
  • 前端工程师应该做什么?:使用LINK标签将样式表放在文档HEAD中

第6章 规则6 - 将脚本放在底部

  • 脚本带来的问题:将脚本放在页面越靠下的地方,意味着越多的内容能够逐步地呈现
  • 并行下载:增加并行下载数量并不是没有开销的,其优劣取决于你的带宽和CPU速度,过多的并行下载反而会降低性能
  • 脚本阻塞下载:一个原因是,脚本可能使用document.write来修改页面内容;另一个原因是为了保证脚本能够按照正确的顺序执行
  • 最差情况:将脚本放在顶部; 页面中的所有东西都位于脚本之后,整个页面的呈现和下载都会被阻塞
  • 最佳情况:将脚本放在底部;不会阻止页面内容的呈现,而且页面中德可视组件可以尽早下载
  • 正确的放置:将脚本放在底部,并且使用defer、async

第7章 规则7 - 避免CSS表达式

  • 更新表达式:问题在于对其进行的求值得频率比人们期望的要高
  • 围绕问题展开工作:创建一次性表达式和使用事件处理器取代CSS表达式
  • 一次性表达式:在执行中重写它本身
  • 事件处理器:尝试使用事件处理器来为特定的事件提供所期望的动态行为

第8章 规则8 - 使用外部JavaScript和CSS

  • 内联 VS 外置:纯粹而言,内联快一些;每个用户产生的页面查看越少,内联JavaScript和CSS的论据越强势;具有完整缓存的页面查看数量占75% - 85%;如果你的网站中德每个页面都使用相同的JavaScript和CSS,使用外部文件可以提高这些组件的重用率
  • 典型的对比结果:三种基准(页面查看、空缓存VS完整缓存和组件重用),有助于确定最好的选择
  • 主页:使用内联方式反而更好的一个例外是主页
  • 两全其美:两项技术使你既可以获得内联的优势,同时也能缓存外部文件;加载后下载:主页加载完成后动态下载外部组件来实现(通过onload);动态内联:如果cookie不存在,就内联JavaScript和CSS。如果cookie出现了,则有可能外部组件位于浏览器的缓存中,并使用了外部文件

第9章 规则9 - 减少DNS查找

  • DNS缓存和TTL
  • 浏览器的视角:大量独立的变量决定了一个特定的浏览器在请求一个主机名时是否会进行远程DNS请求;尽管有DNS规范,但在DNS缓存如何工作上,它给客户端留了较大的灵活性
  • 减少DNS查找:当客户端的DNS缓存为空(浏览器和操作系统都是)时,DNS查找的数量与Web页面中唯一主机名的数量相等

第10章 规则10 - 精简JavaScript

  • 精简:从代码中移除不必要的字符以减少其大小,进而改善加载时间的实践
  • 混淆:和精简一样,也会移除注释和空白,同时还会改写代码
  • 节省:平均下来,JSMin可以使JavaScript文件的大小减少21%,而Dojo Compressor可以达到25%

第11章 规则11 - 避免重定向

  • 重定向的类型:当Web服务器向浏览器返回一个重定向时,响应中就会拥有一个范围在3xx的状态码
  • 重定向是如何损伤性能的:在重定向完毕并且HTML文档下载完毕之前,没有任何东西显示给用户;重定向延迟了整个HTML文档的传输
  • 重定向之外的其他选择:重定向是解决很多问题的简单方式;有一种重定向最为浪费、发生得也很频繁,即发生在URL的结尾必须出现斜线(/)而没有出现时;将用户从旧的URL转移到新的URL的最简单的方式就是重定向;重定向经常用于跟踪用户流量的流向,另一种选择是使用Referer日志来跟踪流量去向;跟踪出站流量除重定向之外的选择是使用信标 - 一个HTTP请求,另一种方式是使用XMLHttpRequest来发送信标;使用重定向的另一种动机是使URL更加美观并且易于记忆

第12章 规则12 - 移除重复脚本

  • 重复脚本 - 却有其事:导致一个脚本的重复有两个主要因素 - 团队大小和脚本数量
  • 重复脚本损伤性能:不必要的HTTP请求和执行JavaScript所浪费的时间;每向页面中添加脚本的额外实例一次,多余的下载和执行问题就会出现一次
  • 避免重复脚本:一种方法是实现一个脚本管理模块;另一种是创建一个称作insertSript的函数

第13章 规则13 - 配置ETag

  • ETag是什么:Web服务器和浏览器用于确认缓存组件的有效性的一种机制; 服务器在检测缓存的组件是否和原始服务器上的组件匹配时又两种方式:比较最新修改日期、比较实体标签;原始服务器通过Last-Modified响应头来返回组件的最新修改日期;ETag的加入为验证实体提供了比最新修改日期更为灵活的机制
  • ETag带来的问题:通常使用组件的某些属性来构造它,这些属性对于特定的、寄宿了网站的服务器来说是唯一的
  • Etag - 用还是不用:如果你的组件必须通过最新修改日期之外的一些东西来进行验证,则ETag是一种强大的方法;如果你无需自定义ETag,最好简单将其移除
  • 现实世界中的ETag

第14章 规则14 - 使Ajax可缓存

  • Web 2.0,DHTML和Ajax
  • 异步与即时:Ajax的一个明显优点就是向用户提供了即时反馈
  • 优化Ajax请求:最重要的方式就是使响应可缓存
  • 现实世界中的Ajax缓存:使Ajax请求可缓存,除了改变HtTP头之外还需要进行更多的工作;响应的个性化和动态本质必须被反映到缓存中,可供采用的最好的方式是使用查询字符串参数;响应可能会应为数据隐私原因而不能缓存

写在后面