React & Vue 编译/运行流程

文章目录

  • 前言
    • [🧩 一、什么是编译阶段 vs 运行阶段?](#🧩 一、什么是编译阶段 vs 运行阶段?)
    • [🧠 二、React 的编译阶段(前端构建时)](#🧠 二、React 的编译阶段(前端构建时))
    • [⚙️ 三、React 的运行阶段(浏览器中)](#⚙️ 三、React 的运行阶段(浏览器中))
    • [🔁 Vue 的区别简析(对比 React)](#🔁 Vue 的区别简析(对比 React))
    • [✅ 总结:React 是否有编译 & 运行阶段?](#✅ 总结:React 是否有编译 & 运行阶段?)
      • [✅ 一句话总结](#✅ 一句话总结)
    • [📊 一、React vs Vue 编译 & 运行阶段对比图](#📊 一、React vs Vue 编译 & 运行阶段对比图)
    • [🧠 二、React Fiber 架构详解(运行时的核心)](#🧠 二、React Fiber 架构详解(运行时的核心))
      • [🎯 目标:](#🎯 目标:)
    • [🧱 1. 什么是 Fiber?](#🧱 1. 什么是 Fiber?)
    • [🔁 2. Fiber 渲染流程(可视化)](#🔁 2. Fiber 渲染流程(可视化))
      • [→ Fiber Tree 构建如下(树形结构):](#→ Fiber Tree 构建如下(树形结构):)
    • [⚙️ 3. Fiber 的调度阶段(分为两大阶段)](#⚙️ 3. Fiber 的调度阶段(分为两大阶段))
      • [Render Phase → 构建新 Fiber Tree](#Render Phase → 构建新 Fiber Tree)
      • [Commit Phase → 执行 DOM 变更](#Commit Phase → 执行 DOM 变更)
    • [⏱ 4. Fiber 的优先级调度模型(React 18+)](#⏱ 4. Fiber 的优先级调度模型(React 18+))
    • [🧪 5. 实际优化建议(使用 Fiber 正确姿势)](#🧪 5. 实际优化建议(使用 Fiber 正确姿势))
    • [✅ 总结一句话](#✅ 总结一句话)
  • 扩展:
    • [✅ 一、React Fiber 生命周期可视化流程图(文本版)](#✅ 一、React Fiber 生命周期可视化流程图(文本版))
    • [🔍 二、React Fiber Tree 控制台调试(自定义 Hook)](#🔍 二、React Fiber Tree 控制台调试(自定义 Hook))
    • [🧪 三、手写模拟 React.createElement → Fiber → DOM Demo(简化版)](#🧪 三、手写模拟 React.createElement → Fiber → DOM Demo(简化版))

前言

React 和 Vue 都有"编译阶段"和"运行阶段" 的概念,但它们的实现方式和目标略有不同,下面我们系统对比解释,并分析 React 的"编译 → 运行"过程。


🧩 一、什么是编译阶段 vs 运行阶段?

阶段 描述
编译阶段 将模板或 JSX 转换为可以执行的 JavaScript 结构(如虚拟 DOM)
运行阶段 执行渲染逻辑:生成 VDOM、比较 diff、更新真实 DOM、触发生命周期

🧠 二、React 的编译阶段(前端构建时)

步骤 说明
✅ JSX 编译 JSX 被 Babel 转换为 React.createElement(...)
✅ TS 转换 TypeScript 被编译为 JS
✅ 打包 使用 Vite/Webpack/Rollup 等构建工具将模块打包
✅ 可选优化 Tree-shaking、代码分割、Babel 插件优化(如 styled-components Babel 插件)

示例:

js 复制代码
// 编写
const el = <h1>Hello</h1>

// 编译后(Babel 做的)
const el = React.createElement('h1', null, 'Hello')

React 编译阶段主要发生在构建工具 + Babel 中,不涉及运行时模板编译(不像 Vue)


⚙️ 三、React 的运行阶段(浏览器中)

当 React 启动后,它进入运行阶段,包含以下核心步骤:

plaintext 复制代码
JSX → React.createElement() → React Element
        ↓
构建 Fiber Tree → Diff → Commit
        ↓
更新 DOM → 执行 useEffect → 渲染完成

具体包括:

步骤 对应机制
构建虚拟 DOM 调用 React.createElement
Fiber 架构调度 调和旧 Fiber 与新 Fiber,生成变更
DOM 操作 document.createElement / appendChild / setAttribute
生命周期执行 执行 useEffectuseLayoutEffect、组件函数体
异步并发调度(React 18) Scheduler + Lane 模型,实现优先级更新 & 中断恢复

🔁 Vue 的区别简析(对比 React)

项目 Vue(Composition / Template) React(JSX + Hooks)
编译阶段 模板 → render() 函数(Vue Compiler) JSX → React.createElement(Babel)
模板语法 模板语言(.vue SFC 模板) JavaScript/JSX(逻辑即模板)
模板静态提升 ✅ Vue 编译时标记静态节点优化 ❌ React 依赖开发者手动 memo/优化
运行时 创建 VNode → Patch → DOM 更新 创建 React Element → Fiber → DOM 更新

✅ 总结:React 是否有编译 & 运行阶段?

阶段 React 有吗? 特点
编译阶段 ✅ 有(靠 Babel、构建工具完成) JSX → createElement,不做模板编译
运行阶段 ✅ 有 React.createElement → Fiber → DOM
模板 AST 编译优化 ❌ 没有 Vue 特有的 Compiler-optimized 模板静态提升

✅ 一句话总结

React 的"编译阶段"更偏向 Babel 转换与打包构建,核心逻辑在"运行时"完成;而 Vue 则有独立的模板编译器,可在编译阶段做更多优化(如静态提升、指令转换)。


太好了!现在我们来深入 React 和 Vue 在编译阶段与运行阶段的对比图 + Fiber 调度机制讲解,帮助你构建对两大框架运行机制的系统认知。


📊 一、React vs Vue 编译 & 运行阶段对比图

plaintext 复制代码
╔═══════════════════════════╦════════════════════════════════════╗
║        Vue (SFC 模板)      ║          React (JSX)               ║
╠═══════════════════════════╬════════════════════════════════════╣
║【编译阶段】                ║【编译阶段】                         ║
║ .vue 模板 → Compiler AST  ║ JSX → Babel → createElement 调用   ║
║ AST → render 函数(VNode) ║ 类型检查 + 构建优化 + minify        ║
║ 静态节点优化(patch flag) ║ React 没有静态提升,靠 memo/useMemo║
╠═══════════════════════════╬════════════════════════════════════╣
║【运行阶段】                ║【运行阶段】                         ║
║ render() → 虚拟 DOM Tree   ║ JSX → React.createElement Tree     ║
║ VDOM Diff & Patch          ║ Fiber 架构:调和 + commit 阶段     ║
║ 生命周期 & 响应式绑定       ║ 函数组件 + Hooks(useEffect 等)    ║
║ 更新 DOM & 执行副作用       ║ 更新 DOM & 执行副作用               ║
╚═══════════════════════════╩════════════════════════════════════╝

🧠 二、React Fiber 架构详解(运行时的核心)

🎯 目标:

将 React 的渲染流程改为可中断、异步、优先级可调的调度模型。


🧱 1. 什么是 Fiber?

  • Fiber 是 React 16+ 的内部核心数据结构,用于描述组件树
  • 每个 Fiber Node 对应一个组件(或 DOM 节点)
  • React 会构建一个 Fiber Tree 来管理渲染/更新流程

🔁 2. Fiber 渲染流程(可视化)

plaintext 复制代码
function App() {
  return (
    <div>
      <Header />
      <Main />
    </div>
  )
}

→ Fiber Tree 构建如下(树形结构):

plaintext 复制代码
App
├── div
│   ├── Header
│   └── Main

每个节点是一个 FiberNode,包含:

ts 复制代码
{
  type: FunctionComponent | host,
  stateNode: 实例或DOM,
  child: FiberNode,
  sibling: FiberNode,
  return: FiberNode,
  alternate: 上一版本 FiberNode,
}

⚙️ 3. Fiber 的调度阶段(分为两大阶段)

阶段 作用
🔧 Render Phase 构建新 Fiber Tree,找出变化 → 可中断(异步)
📦 Commit Phase 应用 DOM 更新、执行副作用 → 同步执行

Render Phase → 构建新 Fiber Tree

plaintext 复制代码
每次更新:
- 创建新 Fiber Tree
- 与旧的 alternate 比较(diff)
- 标记哪些节点需要更新

Commit Phase → 执行 DOM 变更

plaintext 复制代码
- 统一处理 DOM 插入/删除/属性变更
- 执行 useEffect、useLayoutEffect
- 调用 ref 回调

⏱ 4. Fiber 的优先级调度模型(React 18+)

  • 使用 lane 模型 控制不同任务的优先级
  • 支持中断任务 → 插入高优先级任务 → 再恢复原任务

示例:输入框打字

plaintext 复制代码
输入内容时打字 → 高优先级(用户输入)
图片懒加载 → 低优先级(可延迟)

React 会自动控制调度顺序。


🧪 5. 实际优化建议(使用 Fiber 正确姿势)

场景 最佳实践
避免不必要更新 React.memo / useMemo / useCallback
异步加载 React.lazy + Suspense
重计算优化 useTransition(低优先级更新)
动画或高频交互 放入 useLayoutEffect / requestAnimationFrame
大型列表 react-window, react-virtualized

✅ 总结一句话

Vue 的模板编译更偏向"静态优化 +运行时模板解释 ",而 React 的 Fiber 架构则主打"异步调度 + 最小可中断工作单元 ",两者在编译运行路径上虽不同,但都为性能 + 可维护性 +响应效率服务。


扩展:


✅ 一、React Fiber 生命周期可视化流程图(文本版)

plaintext 复制代码
[App 组件函数执行]
        ↓
[React.createElement()]
        ↓
[构建 React Element Tree]
        ↓
[开始构建 Fiber Tree]
        ↓
╔═════════════════════════════════════╗
║ Render Phase(可中断)             ║
║ - 构建新 Fiber 节点                 ║
║ - 与旧 Fiber 比对                   ║
║ - 标记变化(placement、update)     ║
╚═════════════════════════════════════╝
        ↓
╔═════════════════════════════════════╗
║ Commit Phase(同步)                ║
║ - 应用真实 DOM 变更(append/remove)║
║ - 执行 useEffect / ref 回调         ║
╚═════════════════════════════════════╝
        ↓
[页面展示 & 等待用户交互]

🔍 二、React Fiber Tree 控制台调试(自定义 Hook)

可以用以下 hook 来"打印当前组件树结构",模拟观察 Fiber Tree 中的结构关系(开发环境中有用):

ts 复制代码
import { useEffect } from 'react'

export function useDebugFiber(name: string) {
  useEffect(() => {
    console.log(`[Fiber] ${name} mounted`)
    return () => {
      console.log(`[Fiber] ${name} unmounted`)
    }
  }, [])

  console.log(`[Fiber] ${name} rendering`)
}

使用方式:

ts 复制代码
function Child() {
  useDebugFiber('Child')
  return <div>child</div>
}

你会看到:

复制代码
[Fiber] Child rendering
[Fiber] Child mounted
...
[Fiber] Child unmounted

🧪 三、手写模拟 React.createElement → Fiber → DOM Demo(简化版)

这里我们模拟 React 渲染过程(不含调度,仅结构映射):

js 复制代码
// 模拟 JSX 编译产物
const element = {
  type: 'div',
  props: {
    id: 'root',
    children: [
      { type: 'h1', props: { children: 'Hello' } },
      { type: 'p', props: { children: 'World' } }
    ]
  }
}

// 模拟 Fiber 渲染为真实 DOM
function render(vnode, container) {
  const el = document.createElement(vnode.type)

  // 处理 props
  for (const key in vnode.props) {
    if (key === 'children') continue
    el.setAttribute(key, vnode.props[key])
  }

  // 递归处理子节点
  const children = vnode.props.children || []
  children.forEach(child => {
    if (typeof child === 'string') {
      el.appendChild(document.createTextNode(child))
    } else {
      render(child, el)
    }
  })

  container.appendChild(el)
}

// 使用
render(element, document.body)

输出:

html 复制代码
<body>
  <div id="root">
    <h1>Hello</h1>
    <p>World</p>
  </div>
</body>

相关推荐
a别念m19 分钟前
webpack基础与进阶
前端·webpack·node.js
芭拉拉小魔仙33 分钟前
【Vue3/Typescript】从零开始搭建H5移动端项目
前端·vue.js·typescript·vant
axinawang33 分钟前
通过RedisCacheManager自定义缓存序列化(适用通过注解缓存数据)
前端·spring·bootstrap
前端南玖44 分钟前
Vue3响应式核心:ref vs reactive深度对比
前端·javascript·vue.js
哔哩哔哩技术1 小时前
B站在KMP跨平台的业务实践之路
前端
微笑边缘的金元宝1 小时前
svg实现3环进度图,可动态调节进度数值,(vue)
前端·javascript·vue.js·svg
程序猿小D1 小时前
第28节 Node.js 文件系统
服务器·前端·javascript·vscode·node.js·编辑器·vim
Trae首席推荐官1 小时前
字节跳动技术副总裁洪定坤:TRAE 想做 AI Development
前端·人工智能·trae
小妖6661 小时前
uni-app bitmap.load() 返回 code=-100
前端·javascript·uni-app
前端与小赵1 小时前
uni-app隐藏返回按钮
前端·uni-app