Lighthouse 报告中 TBT 过高怎么优化?

令狐明宇 阅读 57

我用 Lighthouse 测了一个 React 页面,TBT(Total Blocking Time)高达 400ms,明明页面看起来挺流畅的,不知道哪里卡住了。试过把一些 useEffect 拆成更小的逻辑,但没效果。

下面是首页一个组件的代码,会不会是这个列表渲染太重了?数据量其实也不大,就 20 条左右:

const ProductList = ({ products }) => {
  return (
    <div>
      {products.map(product => (
        <div key={product.id} className="product-item">
          <h3>{product.name}</h3>
          <p>{product.description}</p>
        </div>
      ))}
    </div>
  );
};
我来解答 赞 3 收藏
二维码
手机扫码查看
2 条解答
ლ红敏
ლ红敏 Lv1
啊,TBT高这个问题我最近也遇到过!虽然你这段列表渲染代码看起来挺简单的,但React的渲染机制有时候会有些隐形坑。

首先可以试试React.memo包裹一下这个组件,防止不必要的重新渲染:

const ProductList = React.memo(({ products }) => {
// 你原来的代码
});


然后我猜你可能在父组件里有频繁的state更新?比如数据请求或者某个全局状态变化。可以加个console.log看看这个ProductList是不是被重复渲染了。

另外400ms确实有点高了,建议你看看这几个地方:
1. 是不是在useEffect里做了同步的繁重计算?特别是首页初始化的那些逻辑
2. 试试把某些非关键的useEffect改成异步执行,用setTimeout(()=>{}, 0)包裹
3. 检查是不是有大量CSS-in-JS的动态样式计算

我上周优化一个类似问题时发现,有个动画库的polyfill在偷偷吃性能,后来换成CSS动画就好了。你们有用什么第三方动画库吗?
点赞
2026-03-06 15:20
奕冉(打工版)
你这代码本身没大问题,20 条数据渲染不至于让 TBT 飙到 400ms。问题大概率在别的地方,但咱们先说这个组件能怎么改。

React 官方文档在 Performance Optimization 章节里明确提到,避免不必要的重新渲染是优化重点。你这个 ProductList 组件每次父组件更新都会跟着重渲染,即使 products 根本没变。

推荐的做法是用 React.memo 包一下:

const ProductList = React.memo(({ products }) => {
return (

{products.map(product => (

{product.name}


{product.description}



))}

);
});


不过说实话,这招救不了 400ms 的 TBT。TBT 高说明主线程被长任务阻塞了,超过 50ms 的任务都会被算进去。

你需要排查这几个方向:

第一,打开 Chrome DevTools 的 Performance 面板,跑一次录制,看看到底是哪个任务在阻塞。红色的长任务会标得很清楚。

第二,检查父组件是不是在疯狂 re-render。React DevTools 的 Profiler 能看到组件渲染次数和耗时。

第三,看看有没有在渲染阶段做重计算,比如 products.filter().map() 这种链式调用,应该用 useMemo 缓存。

第四,检查 useEffect 里有没有同步执行重操作,比如复杂的数据处理、第三方库初始化。这些应该用 requestIdleCallback 或者 setTimeout 延迟执行,或者放到 Web Worker 里。

第五,React 18 的话,确认你用了 createRoot,并发渲染能帮你在某些场景下减少阻塞。

我之前遇到过一个项目,TBT 高是因为一个第三方图表库在 useEffect 里同步初始化,阻塞了 300 多毫秒。改成懒加载后问题就解决了。

你先用 Performance 面板定位一下真正的阻塞点在哪,别瞎优化。
点赞 2
2026-03-02 09:05