知识体系: 从一道面试题说起

我想先抛出一个老生常谈的面试问题:

从输入 URL 到页面加载完成,发生了什么?

这个问题非常重要,因为性能优化的内容都将以这个问题的答案为骨架展开。

我们现在站在性能优化的角度,一起简单地复习一遍这个经典的过程:首先我们需要通过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛出我们的 HTTP 请求,服务端处理完我们的请求之后,把目标数据放在 HTTP 响应里返回给客户端,拿到响应数据的浏览器就可以开始走一个渲染的流程。渲染完毕,页面便呈现给了用户,并时刻等待响应用户的操作(如下图所示)。

我们将这个过程切分为如下的过程片段:

  1. DNS 解析
  2. TCP 连接
  3. HTTP 请求抛出
  4. 服务端处理请求,HTTP 响应返回
  5. 浏览器拿到响应数据,解析响应内容,把解析的结果展示给用户

大家谨记,我们任何一个用户端的产品,都需要把这 5 个过程滴水不漏地考虑到自己的性能优化方案内、反复权衡,从而打磨出用户满意的速度。

从原理到实践:各个击破

我们接下来要做的事情,就是针对这五个过程进行分解,各个提问,各个击破。

具体来说,DNS 解析花时间,能不能尽量减少解析次数或者把解析前置?

能——浏览器 DNS 缓存和 DNS prefetch。

TCP 每次的三次握手都急死人,有没有解决方案?

有——长连接、预连接、接入 SPDY 协议。

如果说这两个过程的优化往往需要我们和团队的服务端工程师协作完成,前端单方面可以做的努力有限,那么 HTTP 请求呢?

——在减少请求次数和减小请求体积方面,我们应该是专家!

再者,服务器越远,一次请求就越慢,那部署时就把静态资源放在离我们更近的 CDN 上是不是就能更快一些?

以上提到的都是网络层面的性能优化。再往下走就是浏览器端的性能优化——这部分涉及资源加载优化、服务端渲染、浏览器缓存机制的利用、DOM 树的构建、网页排版和渲染过程、回流与重绘的考量、DOM 操作的合理规避等等——这正是前端工程师可以真正一展拳脚的地方。学习这些知识,不仅可以帮助我们从根本上提升页面性能,更能够大大加深个人对浏览器底层原理、运行机制的理解,一举两得!

我们整个的知识图谱,用思维导图展示如下:

我们将从网络层面渲染层面两个大的维度来逐个点亮前端性能优化的技能树。

这两个维度的知识面貌各有千秋:在网络层面,我们需要学习一些必需的理论基础作为前置知识。这部分的学习或许不需要大家写特别多的代码,但需要大家对每一个知识点理解透彻,进而应用到自己日常优化的决策中去。网络层面结束后,由本地存储开始,我们会渐渐过渡到浏览器这一端的优化,大家喜闻乐见的“真代码”就会相应地多起来。