Monorepo中Storybook全局装饰器引发依赖错误排查
Storybook中@ngrok/ngrok依赖报错排查
技术栈
- Vite:模块打包器与运行器
- pnpm:包管理器,通过
npx运行Storybook命令(Storybook暂不支持pnpx) - nx:Monorepo项目管理工具
全局装饰器实现(Preview.tsx)
import type { Preview } from "@storybook/react"; import { EtechUiProvider } from "etech-ui-utils"; import React from "react"; // Generated by Storybook const preview: Preview = { parameters: { controls: { matchers: { color: /(background|color)$/i, date: /Date$/i, }, }, }, } export const decorators = [ (Story) => ( <EtechUiProvider configPath="./etech.config.ts" options={{ filter: "etech-ui-utils-tests" }}> <Story /> </EtechUiProvider> )] export default preview;
测试Story代码
import type { Meta, StoryObj } from "@storybook/react"; import Example from "../Example"; import React from "react"; import { EtechUiProvider } from "etech-ui-utils"; const meta: Meta<typeof Example> = { component: Example, }; export default meta; type Story = StoryObj<typeof Example>; export const Primary: Story = { args: { primary: true } };
测试组件代码
import React from "react"; export default function Example() { return <h1>Example</h1>; }
问题描述
运行Storybook后UI出现报错,根源是Monorepo中etech-ui-utils包依赖的universal-fs包含子依赖@ngrok/ngrok,该依赖在浏览器环境中无法正常运行。
已尝试两种无效方案:
- 使用
pnpm patch移除universal-fs中对@ngrok/ngrok的引用,但pnpm-lock.yaml中仍存在该依赖。 - 在Storybook的
main.ts中配置Vite的optimizeDeps.exclude,将相关依赖标记为外部依赖,无效。
可能的问题点与解决方案
1. pnpm patch未正确生效
- 确认patch流程完整:执行
pnpm patch universal-fs后,修改文件必须运行pnpm patch-commit <patch临时文件夹路径>才能将补丁持久化,否则修改不会被应用。 - 检查
pnpm-lock.yaml中universal-fs条目是否包含patched字段,确认补丁已被记录。 - 执行
pnpm ls @ngrok/ngrok查看完整依赖链,确认是否有其他包间接引入了未打补丁的universal-fs版本。
2. Vite外部依赖配置未覆盖场景
optimizeDeps.exclude仅控制预构建行为,若@ngrok/ngrok被etech-ui-utils直接导入,该配置无法阻止其被打包。可尝试用resolve.alias将其指向空模块:
import type { StorybookConfig } from "@storybook/react-vite"; import { UserConfig } from "vite"; import { mergeConfig } from "vite"; import path from "path"; const config: StorybookConfig = { // 原有配置... viteFinal: (config: UserConfig) => { return mergeConfig(config, { resolve: { alias: { '@ngrok/ngrok': path.resolve(__dirname, './empty-module.js') } }, optimizeDeps: { exclude: ["aws-sdk", "nock", "mock-aws-s3", "@ngrok/ngrok", "*.html"], } }); } }; export default config;
新建empty-module.js文件,内容为:
export default {};
3. Monorepo依赖链路问题
- 检查
etech-ui-utils的package.json,确认universal-fs是dependencies还是devDependencies。若为开发依赖但被Storybook环境加载,可调整依赖类型,或在nx项目配置中排除该依赖在Storybook构建中的加载。 - 运行
nx graph查看项目依赖关系,排查是否有其他包间接引入@ngrok/ngrok。
4. Storybook环境的Rollup配置补充
尝试在Vite配置中添加Rollup的外部依赖排除,强化阻止打包的逻辑:
viteFinal: (config: UserConfig) => { return mergeConfig(config, { build: { rollupOptions: { external: ['@ngrok/ngrok'] } }, // 其他配置... }); }
若@ngrok/ngrok仅用于Node.js环境,可在etech-ui-utils中添加环境判断,避免在浏览器环境加载该依赖:
// etech-ui-utils中的相关代码 if (typeof window === 'undefined') { // 仅在Node.js环境加载@ngrok/ngrok相关逻辑 }
内容的提问来源于stack exchange,提问作者Ethan
相关产品推荐
相关产品推荐

