题记:无心间在公司图书馆看到这本书,感受内容写得很不错,很细颇有条理。虽然本身并不是前端工程师,然而也须要对此有所了解,供之后在架构设计、系统优化时考虑这些因素,特在此将对该书进行摘录,供不时之需。也但愿有更多的同行可以了解到这本书,进而提高本身所负责网站的展示速度,给与用户更好地访问体验。css
只有10-20%的最终用户响应时间花在了下载HTML文档上。其他的80-90%时间花在了下载页面中的全部组件上。
HTTP概述
- 压缩
- 条件GET请求
- Expire
- Keep-Alive
规则一、减小HTTP请求
- 图片地图:将多个图片合并成一个,然后经过css定位显示不一样的位置
- CSS Sprites:同上
- 内联图片
- 合并脚本和样式表
规则二、使用内容发布网络(CDN,Content Delivery Network)
规则三、添加Expires头
- Expires头:在这一日期/时间以后,响应将被认为是无效的
- Max-Age: 设置相对有效时间Cache-Control:max-age=100
- 空缓存VS完整缓存:尽量将页面内容放入大缓存中
- 不只仅是图片:图片应该使用缓存,但这一最佳实践不该该仅限于图片
- 修订文件名:为可以获取最新的文件,最有效的解决方案是修改其全部连接,这样,全新的请求将从原始服务器下载最新的内容。
规则四、压缩组件
- gzip:Accept-Encoding:gzip,deflate。gzip是目前最流行和最有效的压缩方法,是最理想的压缩方法
- 压缩内容:压缩脚本和样式表是很是值得的,同时还有XML和JSON在内的文本。图片和PDF不该该压缩,由于它们原本就已经被压缩了。
- 节省率:压缩一般能将响应的数据量减小将近70%
- gzip配置:不一样的web服务器有不一样的gzip配置方式,但大多支持gzip
- 代理缓存:Web服务器基于Accept-Encoding来检测是否对响应进行压缩。无论是否压缩过,浏览器都会基于响应中的其余HTTP头如Expires和Cache-Control来缓存响应。因为压缩的决定是基于Accept-Encoding请求头的,所以须要在服务器的Vary响应头中包含Accept-Encoding。
- 边缘情形:服务器和客户端的压缩对等性看似简单,但必须正确才行。不管是客户端仍是服务器发生错误(发送压缩内容到不支持它的客户端、忘记将压缩内容声明为已经进行了gzip编码等),页面都会被破坏。错误并不会常常发生,但它们是必须考虑的边缘情形(Edge Case)。这种状况虽然能够经过浏览器白名单方式解决,但设置浏览器白名单的指令过于复杂,没法使用HTTP头进行编码。最佳作法是将User-Agent做为代理的另一种判断标准添加到Vary头中Vary:Accept-Encoding,User-Agent
规则五、将样式表放在顶部
规则5对于加载页面所需的实际时间没有太多影响,它影响更多的是浏览器对这些组件顺序的反应。为避免当样式变化时重绘页面中的元素,浏览器会等待位于底部的样式表加载完成后才会呈现,这时浏览器会延迟任何可视化组件。实际上,用户感受缓慢的页面反而是可视化组建加载得更快的页面。使用LINK标签将样式表放在文档的HEAD中能够解决该问题。前端
在使用样式表时,页面逐步呈现会被阻止,直到全部的样式表下载完成。将样式表移到文档head中,这样就能首先下载它们而不会阻止页面呈现。web
规则六、将脚本放在底部
- 并行下载 对响应时间影响最大的是页面中组件的数量,若是一个Web页面平均地将其组件分别放在两个主机名下,总体响应时间将能够减小大约一半。但并行下载数量并非越多越快,由于增长并行下载数量是有开销的,其优劣取决于带宽和cpu速度。
- 脚本阻塞下载 并行下载组件的优势是很明显的,然而,在下载脚本时并行下载实际上被禁用的。即便使用了不一样的主机名,浏览器也不会启动其余的下载。其中一个缘由是,脚本可能使用document.write来修改页面内容,所以浏览器会等待,已确保页面可以恰当地布局。另外一个缘由是为了保证脚本可以按照正确的顺序执行。
在使用脚本时,对于全部位于脚本如下的内容,逐步呈现都被阻塞了。将脚本放在页面越靠下的地方,意味着越多的内容能逐步地呈现。后端
规则七、避免css表达式
规则八、使用外部JavaScript和Css
- 纯碎而言,内联快一些
- 页面查看 每一个用户产生的页面查看越少,内联JavaScript和Css的论据越强势。另外一方面,若是普通用户可以产生不少的页面查看,浏览器极可能将(具备长久的Expires头的)外部文件放在其缓存中。
- 组件重用 若是你的网站中的每个页面都使用了相同的JavaScript和Css,使用外部文件能够提升这些组件的重用率。在这种状况下使用外部文件更加具备优点,由于当用户在页面间浏览时,JavaScript和Css组件已经位于浏览器的缓存中了。
- 动态内联 若是主页服务器知道一个组件是否在浏览器的缓存中,它能够在内联和使用外部文件之间作出最佳选择。尽管服务器不能查看浏览器缓存中有些什么,但能够用cookies作指示器。若是cookie不存在,就内联了JavaScript和Css。若是cookie出现了,则有可能外部组件位于浏览器的缓存中,并使用了外部文件。
规则九、减小DNS查找
Internet是经过IP地址来查找服务器的。因为IP地址很难记忆,一般使用包含主机名的URL来取代它,但当浏览器发送其请求时,IP地址仍然是必需的。这就是Domain Name System(DNS) 所处的角色。DNS也有开销,一般浏览器查找一个给定的主机名的IP地址要花费20-120毫秒。响应时间依赖于DNS解析器(一般由你的ISP提供)、它所承担的请求压力、你与它之间的距离和你的带宽速度。浏览器
- DNS缓存 DNS查找能够被缓存起来提升性能。这种缓存能够发生在由你的ISP或局域网中的一台特殊的缓存服务器上,但这里探讨的是发生在独立用户的计算机上的DNS缓存。在用户请求了一个主机名以后,DNS信息会留在操做系统的DNS缓存中,以后对于该主机名的请求将无需进行过多的DNS查找,至少短期内不须要。·
- 影响DNS缓存的因素 首先,服务器能够代表记录能够被缓存多久。查找返回的DNS记录包含了一个存活时间(Time-to-live,TTL)值。该值告诉客户端能够对该记录缓存多久,尽管操做系统缓存会考虑TTL值,但浏览器一般忽略该值,并设置它本身的时间限制。另外浏览器对缓存的DNS记录的数量也有限制,TTL设置值一般是1天。
- 减小DNS查找 当客户端的DNS缓存为空(浏览器和操做系统都是)时,DNS查找的数量与Web页面中惟一主机名的数量相等。这包括页面URL、图片、脚本文件、样式表、Flash对象等的主机名。减小惟一主机名的数量就能够就能够减小DNS查找的数量。
- 经过使用Keep-Alive和较少的域名来减小DNS查找
规则十、精简JavaScript
JavaScript做为一门解释型语言,是构建Web页面的首选。当以快速原型为基准开发用户界面时,解释语言要优于其余语言。缓存
- 精简 是从代码中移除没必要要的字符以减小其大小,进而改善加载时间的实践。在代码被精简后,全部的注释以及没必要要的空白字符(空格、换行和制表符)都将被移除。对于JavaScript而言,这能够改善响应时间效率,由于须要下载的文件大小减小了。精简JavaScript最流行的工具是JSMin。
- 混淆 是能够应用在源代码上的另一种优化方式。和精简同样,它也会移除注释和空白,同时它还会改写代码。做为改写的一部分,函数和变量的名字将被转换为更短的字符串,这时的代码更加精炼。可是会带来三个弊端:可能引入错误、增长调试难度、须要对JavaScript关键字标记
- 内联脚本 内联的JavaScript块也应该精简
规则十一、避免重定向
重定向用于将用户从一个URL从新路由到另外一个URL,种类有不少,经常使用的是301和302。它是损伤性能的,能够采用Alias、mod_rewirte、DirectorySlash和直接链接代码来避免重定向。服务器
规则十二、移除重复脚本
- 重复脚本--确有其事 开发一个网站须要极大数量的资源,除了核心团队要构建网站外,其余团队也会向页面贡献HTML代码。因为来自不一样团队的不少人都要向页面中添加HTML,很容易想到相同的脚本可能会被添加屡次
- 重复脚本伤害性能 引发没必要要的HTTP请求和执行JavaScript所消耗的时间
规则1三、配置ETag
实体标签(Entity Tag,ETag)是Web服务器和浏览器用于确认缓存组件的有效性的一种机制。减小呈现页面时所必需的HTTP请求的数量是加速用户体验的最佳方式。能够经过最大化浏览器缓存组件的能力来实现这一目标,但当网站被宿主在多于一台服务器上时,ETag头可能会阻碍缓存。cookie
ETag带来的问题 ETag的问题在于,一般使用组件的某些属性来构造它,这些属性对于特定的、寄宿了网站的服务器来讲是惟一的。当浏览器从一台服务器上获取了原始组件,以后又向另一台不一样的服务器发起条件GET请求时,ETag是不会匹配的----而对于使用服务器集群来处理请求的网站来讲,这是很常见的一种状况。默认状况下,对于拥有多台服务器的网站,Apache和IIS向ETag中嵌入的数据都会大大地下降有效性验证的成功率。网络
解决该问题的两种方式:选择ETag的配置方式或者直接移除ETag前端工程师
规则1四、使Ajax可缓存
Ajax表示异步JavaScript和XML(Asynchronous JavaScript and XML),尽管今天除了XML有不少其余选择,最著名的是JSON。Ajax的目的是为了突破Web本质的开始--中止交互方式。向用户显示一个白屏而后重绘整个页面不是一种后的用户体验。而Ajax在UI和Web服务器之间插入了一层。这个Ajax层位于客户端,与Web服务器进行交互以获取请求的信息,并与表现层交互,仅更新哪些必要的组件。它将Web体验从“浏览页面”转变为“与应用程序进行交互”。
Ajax的一个明显优势是向用户提供了及时反馈,由于它异步地从后端Web服务器请求信息。但Ajax并不保证用户就不会一边玩弄本身的手指一边等着“异步JavaScript和XML”返回响应,记住“异步”并无暗示“即时”,这一点很重要。用户是否须要等待的关键因素在于Ajax请求是被动的仍是主动的。被动请求是为了未来使用而预先发起的。主动请求是基于用户当前的操做而发起的。
改善Ajax请求的最重要的方式就是使响应可缓存,前面第四、九、十、十一、13原则也适用于此。
确保Ajax请求遵照性能指导,尤为应具备长久的Expires头。