连续写了两篇《HTTP/2与WEB性能优化》后,今天写这个系列的最后一篇。在正式开始之前,先简单回顾一下前面两篇文章:《HTTP/2与WEB性能优化(一)》的结论是:HTTP/2的ServerPush机制可以让重要的JS、CSS等资源尽快加载,所以不再需要HTTP/1中“在页眉中内联重要资源”的优化方案。《HTTP/2与WEB性能优化(二)》的结论是:HTTP/2支持多路复用,HTTP连接变得很廉价。之前为了节省连接数,不再需要类似“资源合并和资源内联”等优化方式。多路复用可以在一个TCP连接上建立大量的HTTP连接,所以HTTP连接数没有限制。HTTP/1中常见的“静态域名”优化策略不仅无用,而且还有负面作用。需要删除。另外,HTTP/2的头部压缩功能也可以大大减少HTTP协议头部带来的开销。但是HTTP/2并不完美,并不意味着HTTP/2不再需要性能优化。我在本系统第二篇文章末尾写道:据官方预测,HTTP/1彻底退出历史舞台至少需要10年时间。另外,虽然HTTP/2协议允许不使用TSL部署,但是Chrome和Firefox都表示不支持非HTTP/2overTLS,很有可能网站会提供HTTP/1.1,HTTP/1.1overTLS,以及基于TLS服务的HTTP/2。如何在每种情况下都为用户提供最佳体验,需要更深入的优化研究和更精细的优化策略。事实上,除了前两篇文章提到的优化策略需要针对HTTP/2进行调整外,HTTP/1时期的大部分优化策略仍然有效。HTTP/1的WPO并不是一个新话题。每个人都熟悉它。本文只打算列举其中的几个:启用压缩压缩的目的是使传输的数据更小。我们的在线代码(JS、CSS和HTML)会被压缩,图片也会被压缩(PNGOUT、Pngcrush、JpegOptim、Gifsicle等)。对于文本文件,GZip压缩在服务器发送响应之前也很重要,通常压缩后的文本大小会减小到原始大小的1/4-1/3。压缩代码内容已经有成熟的工具和标准流程,服务器端的GZip是标准的,所以“压缩”是一种投资回报率很高的优化方式。使用HTTP缓存任何WEB项目,要提高性能,在所有链接中进行缓存是必不可少的。利用好HTTP协议的缓存机制,可以大大减少数据和请求的传输,是另一种投资回报率很高的优化方式。这里先介绍一下我之前写的HTTP/1.1缓存机制:首先,服务端可以通过响应头中的Last-Modified(***修改时间)或者ETag(内容特征)来标记实体。浏览器会保存这些标签,并在下次请求时带上If-Modified-Since:最后一个Last-Modified的内容或者If-None-Match:最后一个ETag的内容,来询问服务器资源是否过期。如果服务端发现没有过期,则直接返回一个状态码为304,文本为空的响应,告诉浏览器使用本地缓存;如果资源被更新,服务器返回状态码200,新的Last-Modified,Etag和text。这个过程称为HTTP协商缓存,通常称为弱缓存。可以看出协商缓存不会保存连接数,但是缓存生效后会大大减少传输内容(304响应没有文字,一般只有几百字节)。另外,为什么会有两个响应头可以用来实现协商缓存呢?这是因为一开始使用的Last-Modified有两个问题:1)只能精确到秒,无法体现1秒内的多次变化;2)轮询负载均衡算法中,如果每台机器读取的文件修改时间不一致,存在缓存无故失效,缓存得不到更新的风险。HTTP/1.1没有规定ETag的生成规则,一般实现者对资源内容进行归纳,可以解决前两个问题。另一种缓存机制是服务器通过响应头告诉浏览器,在什么时间之前(Expires)或者在多长时间内(Cache-Control:Max-age=xxx),不要再请求服务器了。我们通常称这种机制为HTTP的强缓存。一旦安装了强缓存规则的资源,再次访问时完全没有HTTP请求(Chrome开发者工具的Network面板仍然会显示请求,但会提示来自缓存;Firefox的firebug类似,会提示BFCache),这将显着提高性能。所以我们一般对CSS、JS、图片等资源使用强缓存,而入口文件(HTML)一般使用协商缓存或者不缓存,这样通过修改入口文件的导入URL就可以达到即时更新的目的入口文件中的强大缓存资源。这里也解释一下为什么会有Expire和Cache-Control。还有两个原因:1)Cache-Control功能更强大,对缓存的控制能力更强;2)Cache-Control使用的max-age是相对时间,不受服务器/客户端时间错误的影响。另外,关于浏览器刷新(F5/cmd+r)和强刷新(Ctrl+F5/shift+cmd+r):普通刷新会使用协商缓存,忽略强缓存;强刷新会忽略所有浏览器缓存(并且request头会携带Cache-Control:no-cache和Pragma:no-cache来通知所有中间节点忽略缓存)。浏览器仅在地址栏或收藏夹输入网址、点击链接等情况下使用强缓存减少DNS查询我们知道,建立TCP连接需要知道目标IP,而大多数情况下,域名是给定的到浏览器。浏览器需要先将域名解析为IP。这个过程就是DNS查询,一般需要几毫秒到几百毫秒,在移动环境下会更慢。请求将被阻止,直到DNS解析完成。浏览器通常会缓存DNS查询结果。页面使用的域名(包括子域名)越少,花在DNS查询上的开销就越少。另外,合理使用浏览器的DNSPrefetching技术也是一个很好的做法。减少重定向无论是通过服务端响应头产生的重定向还是通过JS重定向,都可能引入新的DNS查询、新的TCP连接、新的HTTP请求,所以减少重定向也很重要。浏览器基本上会缓存301MovedPermanently指定的重定向,所以对于永久重定向,可以考虑使用状态码301。对于启用HTTPS的网站,配置HSTS策略还可以减少从HTTP到HTTPS的重定向。WEB性能优化是一个系统工程,不可能在这篇文章里说完,所以决定先写到这里。***,推荐一个Chrome扩展:HTTP/2和SPDY指示器,可以在地址栏显示当前网站是否开启了SPDY或者HTTP/2,点击图标可以直接打开Chrome的HTTP/2调试界面,这很方便。
