跳到主要内容

认识

2024年01月07日
柏拉文
越努力,越幸运

一、认识


React 性能优化思路为: 将变化的部分与不变的部分分离。变化的部分可以为: statepropscontext命中性能优化的组件可以不通过 reconcile 生成 workInProgress.child 而是直接复用上次更新生成的 workInProgress.child。因此 React 源码 中的性能优化总结起来有两点:

  1. 将变化的部分与不变的部分分离

  2. 命中性能优化的组件的子组件(不是自身)不需要 render

React 性能优化策略如下:

  1. bailout 策略: 命中 bailout 性能优化策略的组件可以不通过 reconcile 生成 workInProgress.child, 而是复用上次更新生成的 workInProgress.child, 减少不必要的子组件 render

  2. eagerState 策略: 状态更新前后没有变化, 那么没有必要触发更新, 不必要的更新, 没必要开启后续调度流程

二、bailout


bailout 性能优化策略 存在于 beginWork 中, 命中 bailout 性能优化策略的组件可以不通过 reconcile 生成 workInProgress.child, 而是复用上次更新生成的 workInProgress.child, 减少不必要的子组件 renderbailout 四要素为:

  1. props 不变: 比较 props 变化是通过全等比较, 使用 React.memo 后会变为浅比较。

  2. state 不变: 两种情况可能造成 state 不变:

    • 不存在 update

    • 存在 update, 但计算得出的 state 没变化

  3. context 不变

  4. type 不变

bailout 性能优化策略表现为: 如果命中了 bailout 性能优化策略, 那么不会调用 reconcileChildren 生成新的 workInProgress.child

三、eagerState


eagerState 性能优化策略 状态更新前后没有变化, 那么没有必要触发更新, 不必要的更新, 没必要开启后续调度流程。为此需要做:

  1. 当前产生的 update 是当前 fiber 的第一个 update: 通常情况下, 根据update计算state 发生在 beginWork, 而我们需要在 触发更新时 计算状态, 只有满足 当前 fiberNode 没有其他更新 才尝试进入 eagerState 策略, 避免存在有些 update 因为优先级不够被跳过的情况。

    if (
    fiber.lanes === NoLanes &&
    (current == null || current.lanes === NoLanes)
    ) {
    }
  2. 计算更新后的状态

  3. 与更新前的状态做比较

eagerState 性能优化策略表现为: 如果命中了 eagerState 性能优化策略, 那么不会调用 scheduleUpdateOnFiber 开启新的调度流程。