第 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 对宿主只要求实现一组能力,大致这几类(对应你前面学过的每一站):
- 创建实例:
createInstance、createTextInstance(第 8 章completeWork调它造 DOM)。 - 操作树:
appendChild、removeChild、insertBefore(第 17 章 mutation 阶段用)。 - 更新:
commitUpdate、commitTextUpdate(第 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 源码里看不到任何 document 或 window:它依赖的是一个"约定好的接口",不是具体的 UI 平台。
自定义渲染器:一套核心,到处渲染
这个架构的直接收益:想支持一个新平台,只需要实现 host config,不需要碰 reconciler 核心。Fiber 树、diff、调度、Hooks、并发,全部白拿。这就是为什么社区能有 react-three-fiber(渲染到 WebGL)、react-pdf(渲染到 PDF)、各种 react-dom 的变体。它们共享的,就是这套 host config 接口。
动手实验
- 看占位抛错:直接 import 未被打包的
react-reconciler/src/ReactFiberConfig,看它抛"must be shimmed"。 - 看 DOM 实现:在 react-dom 构建里断点
createInstance(react-dom-bindings 的 ReactDOMComponent.js),确认它内部就是document.createElement。 - 找宿主接口:把 reconciler 里 import
ReactFiberConfig的地方都翻出来,数一数 reconciler 一共依赖多少个宿主函数。
小结
- reconciler 不碰真实 UI,只依赖 host config 接口。
ReactFiberConfig.js是运行即抛错的占位,构建期 shim 成渲染器实现(23 行)。- 接口包括创建实例、操作树、更新、能力声明(
supportsMutation等)。 - 同一套核心,react-dom / react-native-renderer / 自定义渲染器各取所需。
- 想支持新平台,只实现 host config 即可,其余全白拿。
- 下一步(选讲):怎么调试源码,第 35 章。