Skip to main content

第 34 章:ReactDOM 与 reconciler 的解耦——host config 与自定义渲染器(选讲)

选讲。前面 30 多章几乎都在讲 react-reconciler,但你可能没注意到一件事:reconciler 从头到尾没见过 document。它算 Fiber 树、diff、调度,唯一的"外界接口"是一个叫 host config 的东西。本章看这个接口怎么让 React 一套核心、到处渲染。

先记住这一句:reconciler 不碰真实 UI,它只依赖一个宿主配置接口(host config)。ReactFiberConfig.js 是个运行就抛错的占位文件,构建期被替换成各渲染器的实现:react-dom 用它操作 DOM,react-native-renderer 用它操作 RN 视图。

一图流:核心算法和宿主怎么解耦

占位文件:明说"你必须被替换"

ReactFiberConfig.js 的整个实现就是一行抛错(ReactFiberConfig.js:23):

throw new Error('This module must be shimmed by a specific renderer.');

这个文件永远不会真正运行。它存在的意义是:如果哪天构建配置坏了,reconciler 误用了这个占位,会立刻报一个明确的错,而不是静默出错。文件的注释也说得很清楚(14):它期望 Rollup/Jest 配置把这个模块 shim 成对应渲染器的实现。

接口长什么样:reconciler 依赖的那几个函数

reconciler 对宿主只要求实现一组能力,大致这几类(对应你前面学过的每一站):

  • 创建实例createInstancecreateTextInstance(第 8 章 completeWork 调它造 DOM)。
  • 操作树appendChildremoveChildinsertBefore(第 17 章 mutation 阶段用)。
  • 更新commitUpdatecommitTextUpdate(第 18 章属性更新)。
  • 能力声明supportsMutation(这个渲染器是不是"改 DOM"型的,react-native 用 persistent 模式就不一样)。

react-dom 的实现里,createInstance 就是 document.createElement(第 8 章见过);对 react-native-renderer,createInstance 变成创建 RN 的宿主视图。同一个 completeWork,调的都是 createInstance,干的活完全不同,这就是解耦。

构建期替换:shim 机制

因为 reconciler 里的 import 是 ReactFiberConfig,而真正的实现在各渲染器里,靠构建工具在打包时做别名替换:react-dom 的构建把 ReactFiberConfig 指向 react-dom-bindings 的实现,react-native-renderer 的构建指向它自己的实现。这也是为什么 reconciler 源码里看不到任何 documentwindow:它依赖的是一个"约定好的接口",不是具体的 UI 平台。

自定义渲染器:一套核心,到处渲染

这个架构的直接收益:想支持一个新平台,只需要实现 host config,不需要碰 reconciler 核心。Fiber 树、diff、调度、Hooks、并发,全部白拿。这就是为什么社区能有 react-three-fiber(渲染到 WebGL)、react-pdf(渲染到 PDF)、各种 react-dom 的变体。它们共享的,就是这套 host config 接口。

动手实验

  1. 看占位抛错:直接 import 未被打包的 react-reconciler/src/ReactFiberConfig,看它抛"must be shimmed"。
  2. 看 DOM 实现:在 react-dom 构建里断点 createInstance(react-dom-bindings 的 ReactDOMComponent.js),确认它内部就是 document.createElement
  3. 找宿主接口:把 reconciler 里 import ReactFiberConfig 的地方都翻出来,数一数 reconciler 一共依赖多少个宿主函数。

小结

  • reconciler 不碰真实 UI,只依赖 host config 接口。
  • ReactFiberConfig.js运行即抛错的占位,构建期 shim 成渲染器实现(23 行)。
  • 接口包括创建实例、操作树、更新、能力声明(supportsMutation 等)。
  • 同一套核心,react-dom / react-native-renderer / 自定义渲染器各取所需。
  • 想支持新平台,只实现 host config 即可,其余全白拿。
  • 下一步(选讲):怎么调试源码,第 35 章。