# Web性能的最佳实践

# DNS查询优化

在与服务主机建立连接之前,需要先解析域名。

  • 限制不同域名的数量
  • 保证低限度的解析延迟
  • 在主体页面 HTML 或响应中利用 DNS 预取指令<link rel="dns-prefetch" href="//ajax.googleapis.com>

# 优化TCP连接

开启新连接是一个耗时的过程。如果连接使用 TLS(也确实应该这么做),开销会更高。降低这种开销的方法如下。

  • 利用 preconnect 指令
  • 尽早终止并响应
  • 实施最新的 TLS 最佳实践 6 来优化 HTTPS

# 避免重定向

重定向通常触发与额外域名建立连接。

  • 利用 CDN 代替客户端在云端实现重定向
  • 如果是同一域名的重定向,使用 Web 服务器上的 rewrite 规则,避免重定向

# 客户端缓存

没有什么比直接从本地缓存获取资源来得更快,因为它根本就不需要建立网络连接。

  • 所谓的纯静态内容,例如图片或带版本的数据,可以在客户端永久缓存
  • CSS/JS 和个性化资源,缓存时间大约是会话(交互)平均时间的两倍
  • 其他类型的资源,理想的 TTL 值会各有不同;这取决于你对特定资源能够容忍的旧数据的极限。所以,你必须结合自身需求来判断最佳值。

# 网络边缘的缓存

因为所有用户都能从云端的共享缓存受益,所以网络边缘的缓存提供了更快的访问速度,也为网站服务基础设施分担了很大一部分流量。如果一份资源需要缓存,它必须满足:

  • 在多用户间可共享,并且
  • 能够接受一定程度的旧数据

# 条件缓存

如果缓存 TTL 过期,客户端会向服务器发起请求。

  • 在请求中包含 HTTP 首部 Last-Modified-Since。仅当最新内容在首部中指定的日期之后被更新过,服务器才返回完整内容;否则只返回 304 响应码,并在响应首部中附带上新的时间戳 Date 字段。
  • 在请求体中包含实体校验码,或者叫 ETag; 它唯一标识所请求的资源。 ETag 由服务器提供,内嵌于资源的响应首部中。服务器会比较当前 ETag 与请求首部中收到的 ETag,如果一致,就只返回 304 响应码;否则返回完整内容。

# 压缩和代码极简化

所有的文本内容( HTML、 JS、 CSS、 SVG、 XML、 JSON、字体等),可以从压缩和极简化中受益。极简化( minification)是指从文本资源中剥离所有非核心内容的过程。通常,这些内容是开发人员敲出来的,所以要考虑方便人类阅读和维护。尽管如此,浏览器并不关心可读性,放弃代码可读性反而能节省空间。
极简化之前:

<html>
<head>
<!-- Change the title as you see fit -->
<title>My first Web page</title>
</head>
<body>
<!-- Put your message of the day here -->
<p>Hello, World!</p>
</body>
</html>

极简化之后:

<html><head><title>My first web page</title></head><body>
<p>Hello, World!</p></body></html>

# 避免阻塞CSS/JS

CSS 的作用是告诉浏览器以什么方式在可视区域的哪个部分渲染内容。所以,在屏幕上绘制第一个像素之前,浏览器必须确保 CSS 已经下载完整。
默认情况下,如果在 HTML 中定位了 JS,它就会被请求、解析,然后执行。在浏览器处理完这个 JS 之前,会阻止其后任何资源的下载渲染。

  • 定期校验这些资源的使用情况。随着时间的变迁, Web 页面可能会持续下载一些不再需要的 JS;这时候,最快速有效的解决办法就是去掉它。
  • 如果 JS 执行顺序无关紧要,并且必须在 onload 事件触发之前运行,那么可以设置async 属性 7,像这样: