背景描述
项目在上线一个异步加载的组件(本质是一个js文件)前,想评估一下该文件的加载时长。为了更全面地了解加载情况,我们需要下面三个数据:
- 平均加载时长
- 首次加载时长(能看出用户最差情况下的加载体验)
- 命中缓存后的加载时长
资源加载测速有很多方法,问题是如何区分该资源加载是命中缓存(浏览器缓存,304协商缓存)后返回的,还是未命中缓存后到线上服务器拉取的。
讨论 & 实际测试得到如下结果,和大家同步一下,感兴趣的同学可以进一步讨论。
解决方案
原理:通过PerformanceTiming中返回的加载信息(各加载阶段的开始时间)来区分缓存加载和网络加载。
方案一:
使用ttfb(发出请求到接收到应答数据第一个字节的时间总和,它包含了DNS解析时间、 TCP连接时间、发送HTTP请求时间和获得响应消息第一个字节的时间)来判断,ttfb = responseStart - requestStart,isCached = ttfb < 10。
方案二:
缓存命中时transferSize为0,需要网络加载时transferSize为具体的包大小。
注意
- ttfb < 10ms,10ms是经验值。存在小概率事件,本地IO堵塞时,ttfb也会大于10ms;
- 【非常关键,一般都在这踩坑】跨域资源,默认responseStart和transferSize返回0,导致ttfb计算为0,上述两个方案都无法区分是否命中缓存。具体参考如下:
针对跨域资源的解决方案
- 推动cdn服务器配置返回头:Timing-Allow-Origin: *
- 【降级方案】【仅针对单个资源】在资源加载后,把资源链接写入localstorage,如果localstorage之前不存在该资源链接,说明是首次,否则是非首次(但是没法确认非首次一定命中缓存)。由此可以得到:平均加载时长和首次加载时长,也能部分满足我的需求
测试数据
未配置支持跨域timing - 未缓存
可以看到在浏览器加载面板能看到ttfb,而通过PerformanceTiming计算会计算出0。
已配置支持跨域timing
PerformanceTiming中responseStart和transferSize不为0
- 未缓存
- 已缓存
最后
如果有别的方法,欢迎一起讨论。
寒冬将至,抱团成长。