---
针对浏览器的优化建议
---

#### 前言

浏览器可远远不止一个网络套接字管理器那么简单，性能可以说是每个浏览器开发商的核心卖点，既然性能如此重要，那浏览器越来越聪明也就毫不奇怪了。预解析可能的 DNS 查询、预连接可能的目标、预取得和优先取得重要资源，这些都是浏览器变聪明的标志。

#### 优化建议

可行的优化手段会因浏览器而异，但从核心优化策略来说，可以宽泛的分为两类：

* 基于文档的优化

  熟悉网络协议，了解文档、CSS 和 JavaScript 解析管道，发现和优先安排关键网络资源，尽早分配请求并取得页面，使其尽快达到可交互的状态。主要方法是优先获取资源、提前解析等。

* 推测性优化

  浏览器可以学习用户的导航模式，执行推测性优化，尝试预测用户的下一次操作，然后，预先解析 DNS、预先连接可能的目标。

好消息是，所有的这些优化都是由浏览器替我们自动完成的，经常可以节省几百 ms 的网络延迟。既然如此，那理解这些优化背后的原理就至关重要了，这样才能利用浏览器的这些特性，提升应用性能。大多数浏览器都利用了如下四种技术：

1. 资源预取和排定优先次序

   文档、CSS 和 JavaScript 解析器可以与网络协议层沟通，声明各种资源的优先级；初始渲染必需的阻塞资源具有最高优先级，而低优先级的请求可能会被临时保存在队列中。

2. DNS 预解析

   对可能的域名进行提前解析，避免将来 HTTP 请求时的 DNS 延迟。预解析可以通过学习导航历史、用户的鼠标悬停，或其他页面信号来触发。

3. TCP 预连接

   DNS 解析之后，浏览器可以根据预测的 HTTP 请求，推测性的打开 TCP 连接。如果猜对的话，则可以节省一次完整的往返（TCP 握手）时间。

4. 页面预渲染

   某些浏览器可以让我们提升下一个可能的目标，从而在隐藏的标签页中预先渲染整个页面。这样，当用户真的触发导航时，就能立即切换过来。

从外部看，现代浏览器的网络协议实现以简单的资源获取机制的面目示人，而从内部来说，它又极为复杂精密，为了解如何优化性能，非常值得深入钻研。那么，在探寻的过程中，我们怎么利用浏览器的这些机制呢？首先，要密切关注每个页面的结构和交互：

* CSS 和 JavaScript 等重要资源应该尽早在文档中出现
* 应该尽早交互 CSS，从而解除渲染阻塞并让 JavaScript 执行
* 非关键性 JavaScript 应该推迟，以避免阻塞 DOM 和 CSSOM 构建
* HTML 文档由解析器递增解析，从而保证文档可以间歇性发送，以求得最佳性能

除了优化页面结构，还可以在文档中嵌入提示，以触发浏览器为我们采用其他优化机制：

```html
<link rel="dns-prefetch" href="//hostname_to_resolve.com">
<link rel="subresource" href="/javascript/myapp.js">
<link rel="prefetch" href="/images/big.jpeg">
<link rel="prerender" href="//example.org/next_page.html">
```

从上到下，依次是：

1. 预解析特定的域名
2. 预取得页面后面要用到的关键性资源
3. 预取得将来导航要用的资源
4. 根据对用户下一个目标的预测，预渲染特定页面

这里的每一个提示都会触发一个推测性优化机制。浏览器虽然不能保证落实，但可以利用这些提示优化加载策略。可惜的是，并非所有浏览器都支持这些提示，不过，如果它们不支持，也只会把提示当做空操作，有益无害。因此，一定要尽早可能利用这些字段。