如何配置Storybook处理Monorepo中跨项目的TypeScript文件?
解决Monorepo中Storybook无法处理跨项目TypeScript文件的问题
问题原因
Storybook默认的Webpack配置只会对当前package内的代码(比如../src/**路径下的文件)应用TypeScript编译规则,Monorepo里其他package(比如你的package2)的文件不在这个处理范围内,导致TS代码没被编译就直接交给Webpack,触发ModuleParseError。
解决方案
1. 修改Webpack规则,让TS loader处理package2的文件
在.storybook/main.ts的webpackFinal中,找到现有的TS/TSX loader规则,把package2的路径加入到规则的include列表里:
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); const path = require('path'); const toPath = (filePath) => path.join(process.cwd(), filePath); // 注意:这里的路径要根据你的Monorepo层级调整,确保指向package2根目录 const package2Path = path.resolve(__dirname, '../../package2'); module.exports = { "stories": [ "../src/**/*.stories.@(mdx|js|jsx|ts|tsx)" ], "addons": [ "@storybook/addon-links", "@storybook/addon-essentials", "@storybook/addon-interactions", "@storybook/addon-knobs/register", "@storybook/preset-create-react-app", "@storybook/addon-a11y", 'storybook-addon-styled-component-theme/dist/preset', 'storybook-addon-themes', "storybook-dark-mode", ], "framework": "@storybook/react", "core": { "builder": "@storybook/builder-webpack5", "disableTelemetry": true, }, features: { emotionAlias: false, }, typescript: { reactDocgen: false }, webpackFinal: async (config, { configType }) => { // 找到处理TS/TSX的loader规则 const tsLoaderRule = config.module.rules.find(rule => rule.test?.test('.tsx') ); // 将package2路径加入到loader的处理范围 if (tsLoaderRule) { tsLoaderRule.include = [...(tsLoaderRule.include || []), package2Path]; } return { ...config, resolve: { ...config.resolve, alias: { ...config.resolve.alias, '@emotion/core': toPath('node_modules/@emotion/react'), 'emotion-theming': toPath('node_modules/@emotion/react'), }, plugins: [new TsconfigPathsPlugin()] }, } } }
2. 同步TS配置,确保跨项目路径被解析
在package1的tsconfig.json中,把package2的路径加入include数组,让TypeScript能识别跨项目的文件:
{ "compilerOptions": { // 原有配置不变 }, "include": [ "src/**/*", "../package2/**/*" ] }
3. 排除Create React App预设的限制(可选)
如果你用的@storybook/preset-create-react-app限制了loader的处理范围,可以尝试移除这个预设,手动配置TS loader:
// 移除addons中的"@storybook/preset-create-react-app" // 然后在webpackFinal中添加TS loader规则 webpackFinal: async (config, { configType }) => { config.module.rules.push({ test: /\.(ts|tsx)$/, include: [ path.resolve(__dirname, '../src'), path.resolve(__dirname, '../../package2') ], use: [ { loader: require.resolve('ts-loader'), options: { transpileOnly: true, configFile: path.resolve(__dirname, '../tsconfig.json') } } ] }); // 保留原有resolve配置 config.resolve = { ...config.resolve, alias: { ...config.resolve.alias, '@emotion/core': toPath('node_modules/@emotion/react'), 'emotion-theming': toPath('node_modules/@emotion/react'), }, plugins: [new TsconfigPathsPlugin()] }; return config; }
验证步骤
修改配置后重启Storybook,检查是否还出现ModuleParseError。如果问题依旧,可以:
- 打印
console.log(config.module.rules)查看TS loader的include范围是否正确 - 确认package2的路径没有写错,是绝对路径
- 检查package2的TS文件是否有语法错误(排除代码本身的问题)
内容的提问来源于stack exchange,提问作者Arseniy
相关产品推荐
相关产品推荐

