ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Storybook Monorepo 配置:修复 workspace 包组件继承 args 缺失的 react-docgen-typescript include 方案

Storybook Monorepo 配置:修复 workspace 包组件继承 args 缺失的 react-docgen-typescript include 方案 Storybook Monorepo 配置修复 workspace 包组件继承 args 缺失的 react-docgen-typescript include 方案【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook导读在 npm/yarn/pnpm workspaces 组织的 monorepo 中使用 Storybook 的react-docgen-typescript解析 React 组件时常会遇到一个隐蔽问题从 workspace 包导入的组件缺少继承而来的 args例如 MUI 的ButtonProps等扩展属性而同一组件在本地源码目录下却能正常工作。本文将基于 Storybook 官方配置片段 storybook-main-rdt-monorepo-include.md深入剖析该问题的成因并给出通过reactDocgenTypescriptOptions.include将 workspace 包源码纳入 TypeScript program 的完整解决方案同时结合仓库源码说明其底层原理帮助你在 monorepo 中稳定地生成组件文档。问题现象workspace 包组件的继承 args 丢失在 monorepo 中使用 npm/yarn/pnpm workspaces 管理多个包例如packages/ui作为共享组件库apps/web作为应用时你可能会发现从 workspace 包如packages/ui导入的组件在 Storybook 的 Controls 面板中缺少继承的 args例如基于 MUI 二次封装的组件ButtonProps这类从父类型继承的属性没有被展示出来而同一个组件如果直接放在本地应用自身的src目录却能正常生成全部 props 文档。这正是 TypeScript 配置文档 中「Inherited args are missing for components from workspace packages」一节描述的场景官方给出的修复方案就是本篇文章所基于的配置片段。根本原因TypeScript program 的 include 范围不覆盖 workspace要理解修复方案必须先弄清楚react-docgen-typescript的工作原理。从仓库源码看当你在 Vite 项目如react-vite、nextjs-vite中把typescript.reactDocgen设置为react-docgen-typescript时Storybook 会在 code/frameworks/react-vite/src/preset.ts 的viteFinal钩子中注入joshwooding/vite-plugin-react-docgen-typescript插件if (reactDocgenOption react-docgen-typescript typescriptPresent) { plugins.push( (await import(joshwooding/vite-plugin-react-docgen-typescript)).default({ ...reactDocgenTypescriptOptions, // We *need* this set so that RDT returns default values in the same format as react-docgen savePropValueAsString: true, }) ); }该插件会根据其includeglob默认值为**/**.tsx从 Storybook 项目目录出发创建一个 TypeScript program并在这个 program 内解析所有组件及其继承关系。默认的 include 模式只会命中 Storybook 项目自身目录下的.tsx文件workspace 包位于该目录之外因而没有进入这个 program。当插件尝试解析 workspace 包组件的继承类型时找不到对应的类型定义继承的 args 自然就丢失了。需要特别指出的是官方文档明确说明了一个常见误区你可能会以为把tsconfigPath指向一个已经包含 workspace 包的 tsconfig 就能解决问题但tsconfigPath只影响编译器选项compiler options的选取并不会改变 TypeScript program 中包含哪些文件。真正决定 program 成员的是include选项。解决方案把 workspace 包源码加入 include修复方式非常简单在typescript.reactDocgenTypescriptOptions中把 workspace 包的源码文件而非编译产物加入include数组。CSF 3 写法传统配置对象// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc. import type { StorybookConfig } from storybook/your-framework; const config: StorybookConfig { framework: storybook/your-framework, stories: [../src/**/*.mdx, ../src/**/*.stories.(js|jsx|mjs|ts|tsx)], typescript: { reactDocgen: react-docgen-typescript, reactDocgenTypescriptOptions: { // Add your workspace package source files so theyre included in the TS program include: [**/*.tsx, ../../packages/ui/src/**/*.tsx], }, }, }; export default config;CSF Next 写法defineMain 函数式配置// Replace your-framework with the framework you are using (e.g., react-vite, nextjs, nextjs-vite) import { defineMain } from storybook/your-framework/node; export default defineMain({ framework: storybook/your-framework, stories: [../src/**/*.mdx, ../src/**/*.stories.(js|jsx|mjs|ts|tsx)], typescript: { reactDocgen: react-docgen-typescript, reactDocgenTypescriptOptions: { // Add your workspace package source files so theyre included in the TS program include: [**/*.tsx, ../../packages/ui/src/**/*.tsx], }, }, });配置要点说明**/*.tsx必须保留它是默认 include 项保证本地src下的组件仍然被纳入 program不能因为加了新路径而删掉它../../packages/ui/src/**/*.tsx按实际目录调整路径是相对于 Storybook 项目.storybook/main.ts所在项目的。若 workspace 包位于其他位置改成对应的相对路径即可建议指向源码目录srcinclude 的是.tsx源文件而不是dist或lib里的编译产物——因为 docgen 需要解析类型声明与继承关系源码才包含完整的类型信息若你有多个 workspace 包可以继续追加多个 glob 条目。深入原理reactDocgenTypescriptOptions 如何被消费Vite 构建器在 Vite 场景下配置会经由 code/frameworks/react-vite/src/types.ts 中的类型定义约束其类型直接来自joshwooding/vite-plugin-react-docgen-typescript插件type TypescriptOptions TypescriptOptionsBase { reactDocgen: react-docgen-typescript | react-docgen | false; /** Configures joshwooding/vite-plugin-react-docgen-typescript */ reactDocgenTypescriptOptions: Parameterstypeof docgenTypescript[0]; };也就是说reactDocgenTypescriptOptions中你能写的选项include、tsconfigPath、compilerOptions、propFilter等与 Vite 插件的参数一一对应。注意 code/frameworks/react-vite/src/preset.ts 中 Storybook 会强制追加savePropValueAsString: true以保证默认值的输出格式与react-docgen保持一致——这是 Storybook 的内部约定你在自定义选项时无需也不建议覆盖它。Webpack 构建器如果你使用的是 Webpack 构建器如react-webpack5相同选项会交给storybook/react-docgen-typescript-plugin。在 code/presets/react-webpack/src/framework-preset-react-docs.ts 中可以看到const { ReactDocgenTypeScriptPlugin } await import(storybook/react-docgen-typescript-plugin); return { ...config, plugins: [ ...(config.plugins || []), new ReactDocgenTypeScriptPlugin({ ...reactDocgenTypescriptOptions, // We *need* this set so that RDT returns default values in the same format as react-docgen savePropValueAsString: true, }), ], };因此本篇文章的修复方案对 Vite 与 Webpack 两类构建器同样适用只是底层插件实现不同Vite 侧为vite-plugin-react-docgen-typescriptWebpack 侧为react-docgen-typescript-plugininclude的语义一致决定 TypeScript program 的成员文件。关联配置项与常见排查围绕react-docgen-typescript还有几个容易混淆或搭配使用的选项一并梳理如下完整定义见 typescript 配置 API 参考选项作用说明reactDocgen选择解析器react-docgen默认快但覆盖不全、react-docgen-typescript调用 TS 编译器慢但更准确、false禁用解析。本方案必须设为react-docgen-typescriptreactDocgenTypescriptOptions传给 RDT 插件的参数依赖reactDocgen为react-docgen-typescript本文的include就在此配置下reactDocgenTypescriptOptions.include决定 TS program 文件范围本方案的核心用于纳入 workspace 包源码reactDocgenTypescriptOptions.tsconfigPath指定 tsconfig 路径只影响编译器选项不影响 program 包含哪些文件无法替代includereactDocgenTypescriptOptions.propFilter过滤 props常用于剔除node_modules中第三方组件的 props可配合include一起使用示例见 storybook-main-prop-filter.mdreactDocgenTypescriptOptions.compilerOptions覆盖编译器选项例如allowSyntheticDefaultImports: false等见 storybook-main-prop-filter.md 中的完整示例如果你发现更普遍的类型生成问题例如Enum或forwardRef的 props 无法正确推断官方建议的通用做法同样是切换到react-docgen-typescript并传入reactDocgenTypescriptOptions: {}完整示例见 storybook-main-react-docgen-typescript.md。验证与注意事项配置修改完成后重启 Storybook 开发服务器include影响的是构建期的 TypeScript program热更新不一定能生效然后打开 workspace 包组件的 Story检查 Controls / Docs 面板中是否出现继承的 props若仍缺失请确认 include 的 glob 与你的 monorepo 目录结构一致例如 packages 是否在../../packages这个层级注意react-docgen-typescript会调用 TypeScript 编译器将更多文件纳入 program 会增加构建耗时这是准确性与性能之间的权衡仅在确实需要解析 workspace 包继承类型时追加路径。小结在 monorepo 中使用 Storybook 为 workspace 包组件生成完整文档时继承 args 缺失的根因是react-docgen-typescript插件创建的 TypeScript program 默认只覆盖 Storybook 项目自身目录**/**.tsx。通过在typescript.reactDocgenTypescriptOptions.include中追加 workspace 包源码路径即可让解析器看到完整的类型继承链——这比调整tsconfigPath更直接有效。结合 code/frameworks/react-vite/src/preset.ts 与 code/presets/react-webpack/src/framework-preset-react-docs.ts 的源码实现可以看到该选项在 Vite 与 Webpack 两种构建器下被一致地透传给底层插件方案具有普适性。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进