被批
中后台想做好很难的……这么多年了技术水平涨没涨,有没有在认真工作?
你以为就表单表格列出来就完事了吗?
后端一页数据返回得多,就是它卡的理由吗?表单多就是它卡的理由吗?
“回去好好研究,解决不了不用回来了!!!”
思绪
“唉“
性能优化是一个永恒的话题啊。
做得再牛再好,一旦卡顿延迟,都会倒人胃口。
随着前端需求复杂度的不断升高,在项目中想始终保持着良好的性能,是一个有挑战的事情。
功课
当你点按钮或输入文字时,网页反应越快越好。理想情况是每次操作后,网页能在16.6毫秒内完成处理(相当于人眼看到的60帧动画的速度)。如果处理时间太长,用户就会觉得卡顿。
通过优化,让网页处理用户操作的速度变快了。用专业工具测量发现,优化后每帧画面的计算时间缩短了。这种流畅度直接影响用户体验,专业术语叫inp指标——反应越快的网页,这个指标就越好。
就像玩游戏要60帧才流畅,网页操作也要快速响应,用户才会觉得顺手不卡。
注释:Interaction to Next Paint(inp),是衡量网页交互性能的指标。用户与网页,交互后,浏览器完成下一次屏幕绘制,所需要的时间。
影响因素:
输入延迟:用户交互与浏览器处理事件之间的时间。
处理时间:事件回调运行所需的时间。
呈现延迟:浏览器绘制新内容所需的时间。
优化:
减少输入延迟:优化主线程任务,避免阻塞。
优化事件回调:简化回调逻辑,使用requestAnimationFrame和setTimeout分散任务,避免长时间运行的任务。
缩短呈现延迟:减少DOM大小,使用content-visibility延迟渲染非关键元素。
评估:
好:INP ≤ 200毫秒。
要优化:200毫秒 < INP ≤ 500毫秒。
差:INP > 500毫秒。
测的工具:
Lighthouse:通过Chrome DevTools生成性能报告,包含INP值,下载好谷歌插件后,直接生成报告即可。
Web Vitals:动态测量INP,便于代码中监控,create-react-app中就看到有web-vitals的身影。
Lighthouse
几种优化建议,提升性能:
减少未使用的 JS 和 CSS: 使用代码分割和按需加载技术;删除无用的 CSS 和 JS 文件。启用文本压缩:配置服务器支持 gzip 或 Brotli 压缩。优化图片加载:使用下一代图片格式(如 WebP);启用懒加载(Lazy Loading)。消除渲染阻塞资源:将关键 CSS 内联到 HTML 中;为非关键资源添加 async 或 defer 属性。优化服务器响应时间:使用 CDN 缓存静态资源,减少重定向请求。
Web Vitals
通过npm包的形式用:
import {getLCP, getFID, getCLS} from 'web-vitals';
getLCP(console.log);
getFID(console.log);
getCLS(console.log);
通过安装谷歌插件:
通过cdn插入代码:
<script>
(function() {
var script = document.createElement('script');
script.src = 'https://unpkg.com/web-vitals';
script.onload = function() {
// When loading `web-vitals` using a classic script, all the public
// methods can be found on the `webVitals` global namespace.
webVitals.getCLS(console.log);
webVitals.getFID(console.log);
webVitals.getLCP(console.log);
}
document.head.appendChild(script);
}())
</script>
网页性能指标报告注意事项整理
-
某些情况不会报告具体指标
- FID(首次输入延迟):如果用户从未与页面交互(如点击、输入等),就不会报告。
- FCP、FID、LCP:如果是**服务端渲染(SSR)**的页面,这些指标可能不会被记录。
-
部分指标的特殊情况
- CLS(累积布局偏移):
- 当页面从可见(
visible)变成隐藏(hidden)时(如切换标签页、最小化窗口),浏览器会计算并报告 CLS。 - 使用浏览器前进/后退导航时,可能会报告 CLS、FCP、FID、LCP。
- 当页面从可见(
- CLS(累积布局偏移):
-
指标报告规则
- 每次发生影响性能的变化时(如布局偏移、新内容加载),浏览器都会重新计算并报告最新值,而不是只记录第一次的数据。
也就是说
- 不是所有指标在所有情况下都会上报,比如
用户不操作就不会有FID,SSR页面可能缺失部分数据。 CLS比较特殊,会在页面隐藏或前进/后退时计算。- 这些指标是动态更新的,每次变化都会重新计算并上报。
流程图解
[上图:展示了:用户操作(如点击)到屏幕更新(渲染完成)的完整流程]
1. Blocking Tasks(阻塞任务)
这些是浏览器主线程必须按顺序执行的任务,如果某个任务耗时过长,就会导致卡顿:
Input received
浏览器接收到用户输入(如鼠标点击、键盘输入)。pointerup/mouseup/click
触发的具体事件(指针抬起、鼠标抬起、点击事件)。这些事件可能伴随 JavaScript 事件监听器的处理。Render
浏览器计算页面布局和样式(重排 Reflow / 重绘 Repaint)。Paint
将渲染结果生成像素数据(光栅化)。Frame presented!
最终帧提交给 GPU 显示到屏幕上。
关键点:如果
Render或Paint阶段耗时超过 16.6ms(60Hz 屏幕的单帧时间),用户会感知到卡顿。
2. Input Delay(输入延迟)
用户操作到屏幕更新的总延迟,可拆解为两部分:
Processing time- 主线程处理输入事件、执行 JavaScript、完成渲染的耗时。
- 如果主线程被长任务(Long Tasks)阻塞(如复杂计算),会导致延迟增加。
Presentation delay- 浏览器将渲染结果提交给 GPU 并显示到屏幕的时间。
- 受 GPU 负载、合成(Compositing)效率影响。
3. Compositing, GPU, and Raster(合成、GPU 与光栅化)
这是渲染管线的后端阶段:
- Compositing(合成)
浏览器将页面分层(Layers)并合并,交由 GPU 处理。优化手段:减少层数、使用will-change提示。 - GPU
负责最终画面的绘制。性能瓶颈:显存不足、复杂特效(如模糊滤镜)。 - Raster(光栅化)
将矢量元素(如 CSS 形状)转换为屏幕像素。大尺寸或复杂元素会增加耗时。
总说
好写,很多可二开;
难写,重难点;
要优化,分析、优化、细分,逐个击破。