ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Storybook 中配置 legacyRootApi:用 React 传统 Root API 挂载组件实现渐进式迁移

Storybook 中配置 legacyRootApi:用 React 传统 Root API 挂载组件实现渐进式迁移 Storybook 中配置 legacyRootApi用 React 传统 Root API 挂载组件实现渐进式迁移【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook当项目依赖的 React 版本达到 18.0.0 及以上时Storybook 会自动切换到 React 18 引入的新 Root APIcreateRoot来挂载渲染组件从而解锁并发特性。如果你的组件库、第三方依赖或测试代码尚未来得及适配新 API可以通过在.storybook/main配置中开启framework.options.legacyRootApi让 Storybook 退回使用传统的ReactDOM.render挂载方式实现逐组件、逐模块地渐进式迁移到 React 18。读完本文你将掌握该选项的定位、四套完整配置写法覆盖 CSF 3 与 CSF Next 的 TS/JS 场景以及它背后的源码实现机制。legacyRootApi 选项是什么legacyRootApi是 React 系列 Storybook 框架如storybook/react-webpack5、storybook/react-vite在framework.options中暴露的一个布尔开关。它被收录于 框架配置选项总表 中官方定义为Requires React 18. Toggles support for Reacts legacy root API.它的核心语义如下适用前提是 React 18只有当项目中安装的 React 版本不低于 18.0.0 时该开关才有意义默认关闭false在 react-webpack 预设的类型定义 与 react-vite 框架的类型定义 中该选项都以default false标注。也就是说Storybook 默认采用新版 Root API设计动机是平滑迁移类型定义注释中明确指出React 18 引入新 Root API 是为了承载并发特性concurrent features等一整套新能力若将该标志置为trueStorybook 便使用传统 Root API 挂载组件帮助团队分步、渐进地迁移到 React 18而不是一次性全量改造。在 官方 FAQ 的 “How do I setup the new React Context Root API with Storybook?” 一节中同样给出了该配置的定位当 React 版本 ≥ 18.0.0 时新 Root API 会被自动使用如果希望在升级过渡期内退出新 API就在.storybook/main.js|ts中开启legacyRootApi。在 main 配置中启用 legacyRootApi启用方式是在.storybook/main配置文件的framework.options中设置legacyRootApi: true。以下四段配置代码完整覆盖了当前 Storybook 的两套 CSF 语法 × 两种语言变体即关联文档 react-framework-options-legacy-root-api.md 的全部内容。CSF 3 语法TS 版本.storybook/main.ts// Replace your-framework with the framework you are using (e.g., nextjs, react-webpack5) import type { StorybookConfig } from storybook/your-framework; const config: StorybookConfig { framework: { name: storybook/your-framework, options: { legacyRootApi: true, }, }, }; export default config;JS 版本.storybook/main.jsexport default { framework: { // Replace your-framework with the framework you are using (e.g., nextjs, react-webpack5) name: storybook/your-framework, options: { legacyRootApi: true, }, }, };your-framework需要替换为你实际使用的框架包名。若基于 Webpack 5通常是storybook/react-webpack5若基于 Vite则是storybook/react-vite使用 Next.js 场景下为storybook/nextjs。注意legacyRootApi并非所有框架都暴露该选项它属于 React 渲染体系上述类型定义也只出现在 react-webpack / react-vite 两类 React 框架的类型中这也是选项表格中 Framework 列为 React 的原因。CSF Next 实验性语法CSF Next 是 Storybook 实验性的下一代入口使用defineMain包装配置对象以获取完整类型推导。该 API 已由各框架包通过node子路径导出例如 react-vite 的 node 入口、react-webpack5 的 node 入口 等。TS 版本.storybook/main.ts// Replace your-framework with the framework you are using (e.g., nextjs, react-webpack5) import { defineMain } from storybook/your-framework/node; const config defineMain({ framework: { name: storybook/your-framework, options: { legacyRootApi: true, }, }, }); export default config;JS 版本.storybook/main.js// Replace your-framework with the framework you are using (e.g., nextjs, react-webpack5) import { defineMain } from storybook/your-framework/node; const config defineMain({ framework: { name: storybook/your-framework, options: { legacyRootApi: true, }, }, }); export default config;底层原理react-dom-shim 的双实现切换legacyRootApi并不是 Storybook 渲染端直接判断的分支条件而是通过预设preset阶段对依赖包的重定向来实现的。核心代码位于 react-dom-shim 预设其工作流程如下getIsReactVersion18or19首先读取options.presets.apply(frameworkOptions)取出用户配置的legacyRootApi若其为true函数直接返回false——即不把当前环境当作 React 18/19 处理哪怕真实依赖版本是 18仅在未开启该开关时才去解析resolvedReact/react-dom包的实际版本检查版本号是否以18、19或0.0.0monorepo 内部开发版开头webpackFinal/viteFinal根据判定结果决定是否注入别名storybook/react-dom-shim→storybook/react-dom-shim/react-16从而把渲染实现替换为 legacy 版本。也就是说开启legacyRootApi: true后即便安装的是 React 18/19Storybook 也会强制走 react-16 那套渲染 shim。而 shim 的两种实现直接对应两代 React 挂载 APIreact-16.tsx传统 APIrenderElement通过ReactDOM.render(node, el, callback)同步完成渲染并借助回调resolveunmountElement使用ReactDOM.unmountComponentAtNode(el)react-18.tsx新 Root API内部维护MapElement, ReactRootrenderElement通过ReactDOM.createRoot(el)创建并缓存 Root再用root.render()挂载unmountElement调用root.unmount()并从 Map 中移除节点。从源码结构可以看出react-18 shim 还针对IS_REACT_ACT_ENVIRONMENTReact Testing 环境做了分支在act环境中直接调用root.render否则通过WithCallback组件在useLayoutEffect中触发resolve从而把异步渲染安全地封装成 Promise供 Storybook 的渲染生命周期等待。何时需要开启 legacyRootApi综合 FAQ、框架选项表格 frameworks.mdx 以及上述源码逻辑以下场景可考虑开启该开关依赖尚未兼容 React 18项目中的某些关键库仍基于ReactDOM.render的旧生命周期模型开发使用新 Root API 时渲染异常逐步迁移期团队已升级到 React 18但希望组件与 stories 保持旧渲染路径待逐个验证后再关闭该开关切回新 API类型注释中 “migrate step by step to React 18” 正指向这种用法使用 preact/compat 等兼容层preset.ts源码中特别处理了 react-dom 无法解析为真实文件路径的情况如被解析到preact/compat此时会保守地返回false走 legacy shim 路径。需要注意该开关仅在 React 18 环境下才被设计为有效选项表格注明 Requires React 18。如果项目本身运行在 React 16/17渲染路径本来就会落在 legacy shim 上无需也无法通过该选项改变行为。若需要与 React 18 的严格模式strictMode选项组合使用两者相互独立strictMode控制是否以严格模式渲染legacyRootApi只决定 Root 的创建与挂载方式。小结legacyRootApi是 Storybook 面向 React 18 迁移期提供的一个“降级开关”默认false走createRoot新 Root API置为true后通过 react-dom-shim 预设 将渲染实现重定向到ReactDOM.render的传统路径。它配合类型层面完备的 框架类型定义 与四套配置写法为团队在向 React 18/并发特性迁移的过程中提供了一条可控、可逐步验证的平滑路径。若你在升级后遇到了与 Root API 相关的渲染兼容问题可先从.storybook/main中临时开启legacyRootApi恢复行为再逐一排查不兼容依赖最终切回默认的新 API 路径。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表