了解资源加载时序

优质
小牛编辑
144浏览
2023-12-01

了解网络下载资源的阶段至关重要。这是修复加载问题的基础。

TL;DR

  • 了解资源时序的阶段。
  • 知道每个阶段提供给Resource Timing(资源时序)API。
  • 在时间轴图表中识别性能问题的不同指示。如连续的透明条或大块绿色。

所有网络请求都被视为资源。当它们通过网络检索时,分为不同的生命周期。Network(网络)面板使用的Resource Timing API和提供给开发者的API是一样的。

注意: 当使用跨源资源的`Resource Timing API`时, 请确保所有资源都有CORS头信息。

Resource Timing API提供了关于每个单独资源接收时间的详细信息。 请求生命周期的主要阶段是:

  • Redirect(重定向)
    • 立即开始startTime
    • 如果发生重定向, redirectStart也会开始计时。
    • 如果重定向发生在此阶段结束时,那么redirectEnd将被采用。
  • App Cache(应用程序缓存)
    • 如果浏览器有缓存,将采用fetchStart时间。
  • DNS
    • domainLookupStart 记录DNS请求开始的时间。
    • domainLookupEnd 记录DNS请求结束的时间。
  • TCP
    • connectStart 记录开始连接到服务器的时间。
    • 如果用了TLS或SSL,secureConnectionStart记录开始连接时间。
    • connectEnd 记录连接完毕时间。
  • Request(请求)
    • requestStart记录请求发送到服务器的时间。
  • Response(响应)
    • responseStart记录最开始的响应时间。
    • responseEnd记录响应结束时间。

1.png

在DevTools中查看

Network(网络)面板中查看完整时序信息,您有三个选择。

  • 将鼠标悬停在时间轴列下的时间图表上。这将显示一个弹出窗口,显示完整的时序数据。
  • 点击任何Requests Table(请求列表)中的条目,并打开该条目的Timing(时序)标签页。
  • 使用Resource Timing API(资源时序API)从JavaScript中检索原始数据。

2.png

这段代码可以在DevTools控制台中运行。它将使用Resource Timing API(资源时序API)来检索所有资源。然后它过滤条目,查找包含style.css名称的条目。如果找到,将被返回。

performance.getEntriesByType('resource').filter(item => item.name.includes("style.css"))

3.png

dt:before { content: "\00a0\00a0\00a0"; } dt strong { margin-left: 5px; } dt.stalled:before, dt.proxy-negotiation:before { background-color: #cdcdcd; } dt.dns-lookup:before { background-color: #1f7c83; } dt.initial-connection:before, dt.ssl:before { background-color: #e58226; } dt.request-sent:before, dt.ttfb:before { background-color: #5fdd5f; } dt.content-download:before { background-color: #4189d7; }
  • Queuing(排队)
  • 如果一个请求排队,则表明:
    • 请求被渲染引擎推迟,因为它被认为比关键资源(如脚本/样式)的优先级低。这经常发生在 images(图像) 上。
    • 这个请求被搁置,在等待一个即将被释放的不可用的TCP socket。
    • 这个请求被搁置,因为浏览器限制。在HTTP 1协议中,每个源上只能有6个TCP连接
    • 正在生成磁盘缓存条目(通常非常快)。
  • Stalled/Blocking (停止/阻塞)
  • 发送请求之前等待的时间。它可能因为进入队列的任意原因而被阻塞。这个时间包括代理协商的时间。
  • Proxy Negotiation (代理协商)
  • 与代理服务器连接协商花费的时间。
  • DNS Lookup (DNS查找)
  • 执行DNS查找所用的时间。 页面上的每个新域都需要完整的往返(roundtrip)才能进行DNS查找。
  • Initial Connection / Connecting (初始连接/连接)
  • 建立连接所需的时间, 包括TCP握手/重试和协商SSL。
  • SSL
  • 完成SSL握手所用的时间。
  • Request Sent / Sending (请求已发送/正在发送)
  • 发出网络请求所花费的时间。 通常是几分之一毫秒。
  • Waiting (TTFB) (等待)
  • 等待初始响应所花费的时间,也称为`Time To First Byte`(接收到第一个字节所花费的时间)。这个时间除了等待服务器传递响应所花费的时间之外,还捕获到服务器发送数据的延迟时间。
  • Content Download / Downloading (内容下载/下载)
  • 接收响应数据所花费的时间。(愚人码头注:从接收到第一个字节开始,到下载完最后一个字节结束)

诊断网络问题

通过Network(网络)面板可以发现许多可能的问题。要找到这些问题需要很好地了解客户端和服务端之间的通信以及协议的限制。

排队或停止阻塞

最常见的问题是很多个请求排队或被阻塞。这表示从单个客户端检索的资源太多。在HTTP 1.0/1.1连接协议中,Chrome限制每个域名最多执行6个TCP连接。如果您一次请求十二个资源,前6个将开始,后6个将排队。一旦其中一个请求完成,队列中的第一个请求项目将开始其请求过程。

4.png

要解决传统HTTP 1的此问题,您需要实现分域。即用多个子域名提供服务资源,将资源拆分到多个子域中,均匀分配。

上面说的修复HTTP 1连接数问题,不适用于HTTP 2连接,反而有害。如果您已部署HTTP 2,不要对您的资源进行域划分,因为它会影响HTTP 2的工作原理。在HTTP 2中,TCP连接多路复用连接的。这消除了HTTP 1的6个连接限制,并且可以通过单个连接同时传输多个资源。

接收到第一个字节的时间很慢

正如我们所看到的,很多绿色。

5.png

TTFB就是等待第一个响应字节的时间,建议在200ms以下,以下情况可能会导致高TTFB:

  1. 客户端和服务器之间的网络条件差,
  2. 要么,服务器端程序响应很慢。

为了解决高TTFB,首先去除尽可能多的网络连接。理想情况下,在本地托管应用程序(部署在本地),并查看是否仍有一个大的TTFB。如果有,那么需要优化应用程序针的响应速度。这可能意味着优化数据库查询,为内容的某些部分实现高速缓存,或修改Web服务器配置。后端可能很慢的原因有很多。您需要对您的程序进行研究,并找出不符合您预期的内容。

如果本地TTFB低,那么是您的客户端和服务器之间的网络问题。网络传输可能被很多种事情干扰阻碍。在客户端和服务器之间有很多点,每个都有自己的连接限制,可能会导致问题。测试减少这种情况的最简单的方法是将您的应用程序放在另一台主机上,看看TTFB是否改进。

加载缓慢

正如我们所看到的,很多蓝色。

6.png

如果您看到Content Download(内容下载)阶段花费了很多时间,提高服务响应速度、并行下载等优化措施帮助都不大。 主要的解决方案是发送更少的字节。(比如,下载一张高质量的大图,可能是几兆,这个时候你需要优化图片。)