资源加载测速区分缓存读取和线上拉取

750 阅读2分钟

背景描述

项目在上线一个异步加载的组件(本质是一个js文件)前,想评估一下该文件的加载时长。为了更全面地了解加载情况,我们需要下面三个数据:

  1. 平均加载时长
  2. 首次加载时长(能看出用户最差情况下的加载体验)
  3. 命中缓存后的加载时长

资源加载测速有很多方法,问题是如何区分该资源加载是命中缓存(浏览器缓存,304协商缓存)后返回的,还是未命中缓存后到线上服务器拉取的。

讨论 & 实际测试得到如下结果,和大家同步一下,感兴趣的同学可以进一步讨论。

解决方案

原理:通过PerformanceTiming中返回的加载信息(各加载阶段的开始时间)来区分缓存加载和网络加载。

方案一:

使用ttfb(发出请求到接收到应答数据第一个字节的时间总和,它包含了DNS解析时间、 TCP连接时间、发送HTTP请求时间和获得响应消息第一个字节的时间)来判断,ttfb = responseStart - requestStart,isCached = ttfb < 10。

方案二:

缓存命中时transferSize为0,需要网络加载时transferSize为具体的包大小。

注意

  1. ttfb < 10ms,10ms是经验值。存在小概率事件,本地IO堵塞时,ttfb也会大于10ms;
  2. 【非常关键,一般都在这踩坑】跨域资源,默认responseStart和transferSize返回0,导致ttfb计算为0,上述两个方案都无法区分是否命中缓存。具体参考如下:

wecom-temp-cf84654662a7fd946aa8051bdf0ccf24.png

针对跨域资源的解决方案

  1. 推动cdn服务器配置返回头:Timing-Allow-Origin: *
  2. 【降级方案】【仅针对单个资源】在资源加载后,把资源链接写入localstorage,如果localstorage之前不存在该资源链接,说明是首次,否则是非首次(但是没法确认非首次一定命中缓存)。由此可以得到:平均加载时长和首次加载时长,也能部分满足我的需求

测试数据

未配置支持跨域timing - 未缓存

可以看到在浏览器加载面板能看到ttfb,而通过PerformanceTiming计算会计算出0。

wecom-temp-126dbb36b2bbacc9297757f58b2eae59.png

已配置支持跨域timing

PerformanceTiming中responseStart和transferSize不为0

  1. 未缓存

wecom-temp-26883aa198027a91840758c207814c95.png

  1. 已缓存

wecom-temp-ff42f90f89b2acdbdf21c802f521e084.png

最后

如果有别的方法,欢迎一起讨论。

寒冬将至,抱团成长。