React+Vite集成Storybook构建时‘keys’导出失败求助
React+Vite+Storybook构建报错:"keys"未被外部包导出的解决思路
问题背景
使用React+Vite集成Storybook时,开发命令storybook dev -p 6006可以正常运行,但执行storybook build时出现Rollup错误:
=> Failed to build the preview RollupError: "keys" is not exported by "../external-package/dist/index.js", imported by "src/components/componentA.tsx".
直接导入import { keys } from 'external-package'无效,但导入源码路径import keys from 'external-package/src/keys'或import * as resources from 'external-package/src/keys'可以正常使用。
当前TypeScript compilerOptions配置:
"compilerOptions": { "module": "commonjs", "target": "es6", "lib": ["esnext"], "declaration": true, "outDir": "./dist", "declarationDir": "./dist/types", "strict": true, "strictNullChecks": true, "alwaysStrict": true, "noFallthroughCasesInSwitch": false, "inlineSourceMap": true, "inlineSources": true, "experimentalDecorators": true, "strictPropertyInitialization": false, "esModuleInterop": true },
核心原因
- 外部包
external-package的dist/index.js产物可能未正确做具名导出,或者仅提供了CommonJS格式的输出。Storybook构建用的Rollup对ES模块解析更严格,而开发时Vite的模块兼容机制更宽松,所以开发阶段没暴露问题。 - 当前TypeScript配置
module: commonjs,编译后的模块格式和Storybook构建工具的ES模块优先逻辑不匹配,加剧了导出解析的冲突。
具体解决方法
1. 修复外部包的打包配置(如果包是你维护的)
- 在包的
package.json中同时声明ES模块和CommonJS入口:
确保打包工具(比如Rollup、Esbuild)生成对应的ES模块产物。{ "main": "dist/index.js", // CommonJS格式 "module": "dist/index.esm.js" // ES模块格式 } - 确认包的入口文件正确做具名导出:
// external-package/src/index.js export { keys } from './keys'; // 或者直接导出 export const keys = { /* ... */ };
2. 配置Storybook的Vite解析规则
在.storybook/main.js中添加viteFinal配置,强制绕过有问题的dist产物,直接使用源码:
module.exports = { stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: ['@storybook/addon-links', '@storybook/addon-essentials'], framework: { name: '@storybook/react-vite', options: {}, }, async viteFinal(config) { // 添加别名,将external-package指向源码目录 config.resolve.alias = { ...config.resolve.alias, 'external-package': 'external-package/src', }; return config; }, };
3. 调整TypeScript的模块配置
把compilerOptions中的module改为ESNext,让TypeScript生成ES模块格式的代码,适配Vite和Storybook的构建逻辑:
"compilerOptions": { "module": "ESNext", // 其他配置保持不变 }
4. 临时兼容方案:全局别名映射
如果上面的方法都无法快速生效,可以在项目的vite.config.js和Storybook的Vite配置中同时添加别名,让常规导入自动映射到源码路径:
// vite.config.js import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], resolve: { alias: { 'external-package': 'external-package/src', }, }, });
内容的提问来源于stack exchange,提问作者Sean Liu
相关产品推荐
相关产品推荐

