Navigation Timing是一个性能优化方面为我们提供精准数据的工具,之前测试页面加载的时间都是在相应的位置打Date.now(),通过计算时间差来实现。这种做法有很多弊端
W3C引入了 Navigation Timing API 帮我们自动,精准的实现了性能测试的打点问题。不仅帮我们省去了繁琐的手动打点的操作,而且提供了以前我们无法获取到的数据,比如DNS和TCP连接所需的时间。
加载一个页面时,一步一步怎么去做的。
注:无上一层页面时,从fetchStart开始
做差值,用来计算重定向完成的时间
可聊点:
1.结合navigationStart,如果没有上一个页面的时候,fetchStart是整个全新开始页面的start
2.浏览器网络层ready的时间(可通过某个点减去fetchStart,计算出该点所用的时间)
网络的建立连接过程:connectEnd减去domainInLookupStart ,就是网络建立连接的耗时
secureConnectionStart
返回浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳。如果当前网页不要求安全连接,则返回0。
建立安全链接 =>发散: http1.0 与 http2.0
整个请求的发起开始到完成接受的耗时
domLoading
开始解析渲染dom的时间(即Document.readyState属性变为“loading”、相应的 readystatechange事件触发时)
domInterActive
完成了dom树的解析(即Document.readyState属性变为“interactive”、相应的readystatechange事件触发时),domInterActive减去domLoading就是解析dom树的时间。
可聊点:
1.完成dom树的解析,是不是整个页面的资源都加载完毕?
不是。只是完成了dom树的解析,并没有开始加载网页资源。
2.dom树的层级多了,会影响dom树解析的速度。
domComplete减去domLoading,dom初始化的时间。
页面的卡顿流畅都是感官上的,以上的数据会给我们理性的衡量标准。
在页面load完之后我们可以从performance.timing对象中拿到我们需要的所有数据:
例1:计算页面加载所需的总时长:
// index.html
<script>
javascript:(() => {
const performance = window.performance.timing;
const pageLoadTime = performance.loadEventEnd - performance.navigationStart;
// pageLoadTime 为所求时间,可进行 打印、上报、存储
console.log('当前页面加载耗时:', pageLoadTime, 'ms');
})()
</script>
例2:计算请求返回时长:
// index.html
<script>
javascript:(() => {
var connectTime = perfData.responseEnd - perfData.requestStart;
// connectTime 为请求返回时长
})()
</script>
什么是CWV ?
Core Web Vitals (核心页面指标)是一种速度指标,是 Google 用于衡量用户体验的页面体验信号的一部分。 这些指标衡量是:最大内容绘制 (LCP) 的视觉负载、累积布局移位 (CLS) 的视觉稳定性、以及首次输入延迟 (FID) 的交互性。
加载、交互、视觉稳定 —— 代表不同方向的衡量标准 + 可衡量且接近真实体验的数据化参数
LCP 衡量加载性能——内容出现的速度。
最大内容绘制 (LCP) 报告视口内可见的最大图像或文本块的渲染时间。低于 2.5 秒的时间被认为是好的,而高于 4.0 秒的任何时间都被认为是差的。
要求:页面加载2.5s内,必须要进行最大内容的渲染。
什么是最大内容?
- 图片:
、、 - 通过url加载内容的模块(包括带有使用 CSS url()属性加载的背景图像的元素)
- 主要文本模块以及其内联模块(包含文本节点的块级元素)
2.1.1 LCP低下的原因(提升LCP的感知程度)
1.资源慢
解决=>缓存:强缓存+协商缓存
2. 渲染被阻断
解决=> 对于复杂的结构 :简化结构与逻辑、内联合并(结构、解析、脚本变简单,减少频繁的dom操作。 如MVVM框架,做一些dom diff,合并对于dom的频繁操作,改成一次性操作,尽量不去打断渲染)
3. 资源交互
图片分类 - 同一个图片分成几种(最大化提效,小页面不需要高精度,如列表页,只需要略缩图,不需要高清图。降低图片的质量和大小,提升最大内容的可显示速度,提高用户主观感受)
4. 静态资源
走CDN
FID 衡量响应能力——页面对用户操作的响应速度。
该指标记录从用户与页面交互(点击、点击、按键等)到浏览器开始处理该事件处理程序的时间。小于 100 毫秒的延迟被认为是好的,而超过 300 毫秒的任何延迟都被认为是差的。
注: 它只测量事件处理的延迟——而不是运行处理程序或更新 UI 所花费的时间。
如果说LCP是衡量用户的第一眼感受的话,FID是衡量交互体验
要求:页面首次输入延迟小于100ms
2.2.1 FID的改进方式
1 减少 JavaScript 执行时间
a.优化算法
b. 尽量减少JS的占用 (空间、时间)
空间:进行压缩,减少JS的体积
c. 首屏加载
如何优化SPA?
- 服务端渲染
解决SPA问题:不用SPA,后台渲染好,返回静态页- 使用预加载、懒加载
2. 分解长时间运行的任务(解决长任务问题)
长任务:一个任务可能会阻塞整个渲染。阻塞渲染50ms以上。
解决:
*3 提升性能来帮助提速(使用Web Worker在后台线程中运行任务)
JS workers:Web wor ·ker | service worker | worklet
// 1. web worker
/* main.js */
// 新增一个worker
const worker = new Worker('worker.js');
// main thread 通信
worker.postMessage('Come on & work~');
worker.onmessage = function(e) {
console.log(e.data);
}
/* worker.js */
self.onmessage = function(e) {
console.log(e.data);
// 回调主人喊话 => 业务逻辑
// 完成后发给main
self.postMessage(/* 业务逻辑 */);
}
// 2. service worker - 网络 + 内存
/* main.js */
navigator.seviceWorker.register('service-worker.js');
/* service-worker.js */
self.addEventLister("install", function() {});
self.addEventLister("activate", function() {});
self.addEventLister("fetch", function(e) {
e.respondwith(
caches.match(event.request);
)
});
// 3. worklet
// 浏览器概念流程: JS => style => layout => paint => composite
/* main.js */
CSS.paintWorklet.addModule('worklet.js');
/* worklet.js */
registerPaint('myGradient', class {
paint(ctx, size, prop) {
var gradient = ctx.createLinearGradient(0, 0, 0, size.height - 5);
gradient.addColorStop(0, "black");
gradient.addColorStop(1, "white");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, size.width, size.height);
}
})
/* app */
.content {
background-image: paint(myGradient);
}
CLS 测量视觉稳定性 -查看页面时内容的意外移动。
衡量视觉稳定向
要求:页面要保持CLS小于0.1(可见元素从前一帧到后一帧改变位置的动作 就代表视觉稳定性)
可见元素已经在处于可见态,前一帧到后一帧位置动作的改变就是降低视觉稳定性的一种体验。页面点击一下或者加载的时候,本来出现在左边突然间往右移,闪烁和漂移,这是主观上的感受,量化之后就是CLS。
换句话说:如果页面上的元素随着页面加载而移动,那么CLS就会变高,这是不好的。相反,你应该希望页面元素在加载时相当稳定。这样,当页面完全加载时,用户不必重新学习链接,图像和字段的位置,或者错误地点击某些内容。
2.3.1 减少 CLS(如何保持视觉稳定性?)
1 不使用无尺寸元素
对任何媒体(视频、图片、GIF、信息图表等)使用设置大小属性维度:这样,用户的浏览器就可以确切地知道该元素将在该页面上占用多少空间。
扩展: 自适应并不是无尺寸,是一定衡量标准下的有尺寸
srcset & sizes
<img srcset="zhaowa-320w.jpg 320w,
zhaowa-480w.jpg 480w,
zhaowa-800w.jpg 800w,"
sizes="(max-width: 320px) 300px,
(max-width: 480px) 440px,
800px">
2 减少内容内部的插入
(减少 重绘、重排)
会影响到整体的布局
3 字体控制
字体变化大小会导致 外层容器的变化,font-style、font-family变化也会导致视觉上元素不稳定。
对于字体,目标是尽可能快地在屏幕上显示字体,而不是与其他字体交换。在加载网络字体时避免 FOUT(无样式文本的闪烁)和 FOIT(不可见文本的闪烁)。预加载或使用类似大小的后备字体将有所帮助
下载 Core Web VItals Annotetions 点击这里
2.4.1 使用
例:使用Core Web VItals Annotetions测试百度翻译
右侧展示为FID、LCP、CLS测量信息,页面中标注为CLS偏移部分。
2.4.2 高效的优化方法
评估 LCP、FID 和 CLS 指标可以帮助确定最关键的问题。解决快速而简单的问题——它们通常具有最大的投资回报:
performance定位神器:接到一个任务,这个页面比较慢、性能差。属于感官上的感受 ,不好量化。performance可以把它量化出来,并找到慢的原因。
可把performance理解为对性能评估领域的一个接口,可以通过performance拿到很多性能上的参数,通过performance去定位哪里有问题,哪里有问题改哪里。
一个页面性能评估的领域:
1.存储有没有问题:FPS(帧率),CPU(占用、资源的消耗)、网络请求(的多少)
2.网络请求有没有问题:网络任务队列(如何排列的,并行还是串行)
3.代码执行有没有问题:JS消耗时间、性能占用(确认代码的书写有没有需要改进的地方)
4.布局(layout) 有没有问题:浏览器绘制页面的帧布局
由于本文篇幅较长,故提取成单独文章:
点击查看-使用详解
比较完善,自动化的形式,规则的去看系统的性能
growing.io => fineBi / powerBi => grafana => 钉钉、企业微信、飞书 webhook
BigPipe 是由 Facebook提出来的一种动态网页加载技术。它将网页分解成称为 pagelets 的小块,然后分块传输到浏览器端,进行渲染。它可以有效地提升首屏渲染时间。
为了使得浏览器和服务器可以并行的执行某些操作,BigPipe 首先需要我们将网页分割成被称为 pagelet 的小块。然后我们将网页交付流程分解为如下阶段:
- 服务前端接收客户端请求
- node生成HTML * n => 若干个pageLet
- 浏览器获取到pagelet后开始加载资源做layout paint
- 客户端整合形成页面