概览Profiler 能采集渲染的开始/结束时间与开销,结合 INP 可定位输入到响应的瓶颈,从而采取任务切分与过渡更新策略提升体验。采集渲染开销'use client'
import React, { Profiler, useState, useTransition } from 'react'
function onRender(id: string, phase: 'mount' | 'update', actualDuration: number) {
navigator.sendBeacon('/api/render', JSON.stringify({ id, phase, actualDuration }))
}
export default function App() {
const [list, setList] = useState<string[]>([])
const [pending, startTransition] = useTransition()
function add(v: string) {
startTransition(() => setList((prev) => [...prev, v]))
}
return (
<Profiler id="List" onRender={onRender}>
<input onChange={(e) => add(e.target.value)} />
{pending && <p role="status">更新中…</p>}
<ul>{list.map((s) => (<li key={s}>{s}</li>))}</ul>
</Profiler>
)
}
INP 采集关联'use client'
let maxEvent = 0
const po = new PerformanceObserver((list) => {
for (const e of list.getEntries() as PerformanceEventTiming[]) {
if (e.name === 'click' || e.name === 'pointerdown' || e.name === 'keydown') {
maxEvent = Math.max(maxEvent, e.duration)
}
}
})
po.observe({ type: 'event', buffered: true, durationThreshold: 16 })
addEventListener('beforeunload', () => {
navigator.sendBeacon('/api/vitals', JSON.stringify({ inp: maxEvent }))
})
治理要点将昂贵更新标记为过渡,避免阻塞输入路径;对超大列表采用分页与虚拟化。切分长任务并让渡主线程;与缓存策略协作减少重复计算。使用 `role="status"` 提示挂起状态,兼顾可访问性。验证与指标React:19.0+;Next.js:15.0+渲染开销与 INP 关联清晰;输入响应与列表更新稳定

发表评论 取消回复