link,[object Object]
Skip to content

花里胡哨的代价:INP 1128ms ​

第一章。

我是比较喜欢各种各样花里胡哨的 UI、UX 的,所以在这个网站开发的初期,我设计了很多,但是在网页的具体打开之后,我发现十分的卡顿。最开始我以为只是代码的问题,没有提升流畅度,以为帧率开的不够高——

补:帧率不是「开」出来的设置,它是每一帧渲染工作量多少的结果——每帧的活儿少了,帧率自然就高。所以「把帧率开高」从来不是解法,让每帧少干重活才是。

但是后来我打开开发者工具之后,点击性能,我看到我的 INP 达到了 1128ms,这也太离谱了(补:INP 合格线 200ms 以内,超过 500ms 就判「差」,1128 属于离谱中的离谱),这说明每一个设计后面都绑定了太多的 JS 逻辑,一个优秀的网站不应该是冗余的。

我开始排查,然后我发现首屏那个魔法阵消散直接导致了卡顿,那个消散我是设计为像物质溶于水一样的,但是这个好像是一个比较重的重绘动画,假如重绘动画多了,会挤占 CPU,然后也会导致 INP 大幅增加。

补:浏览器出一帧画面有三条路,成本差很远——合成(已经画好的图层整体挪位置、改透明度,最便宜,走独立线程)→ 重绘(图层内容变了,每个像素都得重画,贵)→ 回流(布局变了,前后全部重排,最贵)。transform / opacity 动画只走「合成」这条路,所以「动效只动 transform 和 opacity」是铁律;消散这种滤镜动画走的是「重绘」,等于每帧把整个图层重画一遍,这就是卡顿的来源。

要么就是砍掉这个设计,要么就是整体实现一个淡入淡出即可,然后网站可以设计为,切换页面之后,其他页面的动效都停下来。

顺手学的知识 ​

我也学习了一些其他的知识,比如说页面的动画,比如说纯 CSS,或者 CSS+JS,好像有个叫 SVG 动画,动画分为 SVG 动画和普通 DOM 动画(补:按驱动方式还能再分一层——纯 CSS 的 animation / transition,声明式交给浏览器调度;CSS + JS 的 Web Animations API、requestAnimationFrame,更灵活但跑在主线程上;SVG 还有自己的 SMIL)。

然后好像也有一个知识,是关于浏览器的,叫合成器,还有一个叫滤镜,前者走独立线程,然后就是一个打螺丝的工人(补:合成器只负责把已经画好的图层摆好、挪动,不碰内容,所以主线程再堵也拦不住它干活),但是滤镜容易退回主线程,然后是一个脑力干部,会修改图层里的每一个像素颜色,那个魔法阵的消散效果或许就是滤镜推到了主线程上(补:滤镜不是一概不能用——一次性渲染的静态滤镜代价有限,真正要命的是动画过程中数值一直在变的滤镜(blur、drop-shadow、SVG 滤镜),那等于每帧重绘一遍)。

DOM 可以理解为,将 HTML 解析给 JS 和 CSS 操控的节点树。

DOM 动画可以实现:移动、缩放、旋转、透明度、颜色变化,但是因为不擅长矢量图形,所以基本上都是规则图形,而 SVG 擅长这个,所以两者可以互补,构成了动画体系。

JS 基本都是跑在主线程上的(补:除非另开 Web Worker,否则主线程一堵就是「点了没反应」——INP 量的正是这段堵车时间)。

三大黄金指标 ​

衡量网页体验的三大黄金指标:LCP、CLS、INP(补:三个合称 Core Web Vitals)。

LCP:页面开始加载后,最大的一块内容元素渲染出来的时间,代表用户什么时候第一眼看到页面主体内容(衡量「加载速度」,合格线 2.5 秒以内)

CLS:页面加载过程中,元素突然乱跑、抖动、跳位置的总分(衡量「页面稳不稳,会不会突然移位坑用户点错」,合格线 0.1 以下)

INP:用户点击、打字、触摸等操作后,到页面做出视觉反馈的延迟(衡量「交互响应快不快」,也就是你之前关心的主线程卡顿,合格线 200ms 以内)