文章目录
- 前言
-
- [🧩 一、什么是编译阶段 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 |
生命周期执行 | 执行 useEffect 、useLayoutEffect 、组件函数体 |
异步并发调度(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>