四年!!React 你知道我这四年怎么过的吗

首页 编程分享 JQUERY丨JS丨VUE 正文

寅时码 转载 编程分享 2025-11-04 20:10:00

简介 React Compiler 发布 1.0 稳定版,告别手动 Memo;React 19.2 更新 Activity、useEffectEvent 等新特性。终于不用手动封装 KeepAlive了..


好事连连

  • React 脱离 Facebook,成立基金会(以前 React 被 Vercel Nestjs 夺舍,更新的都是无用功能,对于开发体验毫无提升)
  • React 19.2 更新 Activity、useEffectEvent 等新特性。终于不用手动封装 KeepAlive
  • React Compiler 发布 1.0 稳定版,告别手动 Memo

好事连连啊

那些年被 React 折磨的日子

从 React Forget 到 babel-plugin-react-compiler,这四年的等待终于有了结果

还记得 2021 年 React Conf 上,React 团队首次展示了那个让人眼前一亮的项目——React Forget。当时我就想,终于!React 终于要解决那个让人头疼的性能问题了。

四年过去了,从 React Forget 到现在的 babel-plugin-react-compiler 1.0,这四年的等待让我深刻体会到了什么叫"望眼欲穿"。

React 的"愚蠢":为什么我们需要手动优化?

那些年我们写过的"屎山"代码

在 React 的世界里,性能优化一直是个让人头疼的问题。每次组件的 stateprops 发生变化,React 都会从根节点开始对比,判断哪些节点需要更新。这种机制导致了大量不必要的重新渲染。

为了避免这些不必要的渲染,我们不得不在代码里写满这样的 memo "屎山":

const ExpensiveComponent = React.memo(({ data, onUpdate }) => {
  const processedData = useMemo(() => {
    return data.map(item => ({
      ...item,
      processed: expensiveCalculation(item)
    }))
  }, [data])

  const handleClick = useCallback(() => {
    onUpdate(processedData)
  }, [processedData, onUpdate])

  return (
    <div onClick={handleClick}>
      {processedData.map(item => (
        <Item key={item.id} data={item} />
      ))}
    </div>
  )
})

Vue 的"优雅":细粒度响应式更新

再看看 Vue,人家是怎么做的:

<template>
  <div @click="handleClick">
    <Item 
      v-for="item in processedData" 
      :key="item.id" 
      :data="item" 
    />
  </div>
</template>

<script setup>
const processedData = computed(() => {
  return data.value.map(item => ({
    ...item,
    processed: expensiveCalculation(item)
  }))
})

const handleClick = () => {
  onUpdate(processedData.value)
}
</script>

简洁、优雅、自动优化。Vue 的细粒度响应式更新机制能够自动追踪数据的变化,并仅更新受影响的组件。开发者无需手动进行复杂的优化操作,代码更加直观和高效。

React Compiler:四年的等待终于有了结果

从 React Forget 到 babel-plugin-react-compiler

2021 年,React 团队在 React Conf 上首次展示了 React Forget 项目。这个项目的目标很明确:通过编译器自动优化组件的渲染性能,让开发者无需手动添加 React.memouseCallbackuseMemo 等优化代码。

经过四年的打磨,这项技术终于以 babel-plugin-react-compiler 的形式与开发者见面,现已发布稳定版 1.0

自动化的性能优化

React Compiler 通过静态分析代码,在编译阶段自动为组件添加必要的优化:

这是我写的源代码

import { useState } from 'react'

export default function App() {
  const [count, setCount] = useState(0)

  return (
    <div className='h-screen w-screen flex justify-center items-center flex-col gap-8'>
      <Comp1 />
      <button onClick={ () => setCount(count + 1) }>+</button>
      <button onClick={ () => setCount(count - 1) }>-</button>
      <p>{ count }</p>
      <Comp2 />
    </div>
  )
}

function Comp1() {
  return <div className="text-red-500 size-16 bg-indigo-300">Comp1 { Math.random() }</div>
}

function Comp2() {
  return <div className="text-blue-500 size-16 bg-green-300">Comp2 { Math.random() }</div>
}

接下来配置一下 Vite,看看编译产物,先关闭代码混淆压缩

在开启 React Compiler 打包后的结果如下

关闭 React Compiler 打包后的结果如下

就这么简单!无需修改任何业务代码,编译器会自动处理所有的性能优化。

没有 React 19.2 以前,需要自己解决 KeepAlive 问题

过去实现组件状态保持(KeepAlive)是个老大难问题

很多人可以认为 display: none 能解决一切,那只能说明的开发经验太浅了

display: none 的局限

  • 组件仍会渲染和初始化
  • 获取不到正确的 DOM 尺寸
  • 会触发生命周期和副作用
  • 多个隐藏组件会造成性能浪费

以前我是自己封装 KeepAlive 组件,需要借助 Suspense 挂起渲染,或手动管理组件卸载,代码复杂且容易出问题,代码大致思路如下

import type { KeepAliveProps } from './type'
import { memo, Suspense, use } from 'react'
import { KeepAliveContext } from './context'

const Wrapper = memo<KeepAliveProps>(({ children, active }) => {
  const resolveRef = useRef<Function | null>(null)

  if (active) {
    resolveRef.current?.()
    resolveRef.current = null
  }
  else {
    throw new Promise((resolve) => {
      resolveRef.current = resolve
    })
  }

  return children
})

/**
 * 利用 Suspense 实现的 KeepAlive 组件
 * 当 active 为 false 时,抛异常,触发 Suspense 的 fallback
 * 当 active 为 true 时,resolve 异常,触发 Suspense 的正常渲染
 */
export const KeepAlive = memo(({
  uniqueKey: key,
  active,
  children,
}: KeepAliveProps & { uniqueKey?: keyof any }) => {
  const { findEffect } = use(KeepAliveContext)
  /**
   * 触发钩子
   */
  useEffect(() => {
    const { activeEffect, deactiveEffect } = findEffect(key)

    if (active) {
      activeEffect.forEach(fn => fn())
    }
    else {
      deactiveEffect.forEach(fn => fn())
    }
  }, [active, findEffect, key])

  return <Suspense fallback={ null }>
    <Wrapper active={ active }>
      { children }
    </Wrapper>
  </Suspense>
})

好起来了

四年的等待,从 React Forget 到 babel-plugin-react-compiler,React 终于迎来了自动化的性能优化时代。并且还带来了 React 19.2 各项好特性,终于不是 SHIT SSR

虽然 React 在性能优化方面曾经被诟病,虽然我们曾经写过无数的"屎山"代码,虽然 Vue 等框架在响应式更新方面确实更加优雅,但 React Compiler 的到来无疑为 React 开发者带来了福音。

它通过自动化的性能优化,简化了开发流程,降低了出错的风险。开发者可以专注于业务逻辑,而无需担心性能优化的细节。

四年的等待值得吗?我想说,值得。因为这意味着 React 正在迎头赶上,为开发者提供更高效、更便捷的开发体验。

转载链接:https://juejin.cn/post/7561003328424394802


Tags:


本篇评论 —— 揽流光,涤眉霜,清露烈酒一口话苍茫。


    声明:参照站内规则,不文明言论将会删除,谢谢合作。


      最新评论




ABOUT ME

Blogger:袅袅牧童 | Arkin

Ido:PHP攻城狮

WeChat:nnmutong

Email:nnmutong@icloud.com

标签云