同一项目集成Vue与Preact组件库时Storybook运行报错
单项目整合Vue/Preact双组件库Storybook启动报错修复方案
基础信息
- 项目场景:单仓库内同时维护适配Vue.js、Preact的两套UI组件库,已通过统一Rollup脚本完成双产物构建,为两套组件库分别配置独立Storybook启动脚本与配置目录后,启动时触发两类报错
- 运行环境:Node.js 12.22.0
报错1修复:Preact版Storybook启动触发ERR_INVALID_ARG_TYPE类型错误
报错特征
执行
yarn storybook:react时抛出TypeError [ERR_INVALID_ARG_TYPE],提示"id" argument must be of type string. Received an instance of Object,错误堆栈指向Storybook核心模块preset加载逻辑。
根因
两套Storybook配置未做路径隔离,Storybook默认向上遍历目录查找preset与缓存配置时,误加载了Vue侧的对象格式预设,将对象传入仅接受字符串路径的模块加载逻辑触发类型错误。
修复步骤
- 修改Preact版Storybook配置文件
.reactStorybook/main.js,显式限定配置查找范围:const path = require('path') module.exports = { // 保留原有stories、addons配置 core: { disableTelemetry: true, // 对应实际使用的builder版本即可 builder: 'webpack5' }, // 显式写全所有preset的完整包名,禁止向上模糊查找 presets: ['@storybook/preact/preset'], // 锁定当前配置目录,禁止向上遍历查找其他配置文件 configDir: path.resolve(__dirname) } - 修改
package.json中Preact版Storybook启动脚本,显式指定配置目录,加参数禁用管理器缓存:{ "scripts": { "storybook:react": "start-storybook -p 6006 -c .reactStorybook --no-manager-cache" } } - 执行
rm -rf node_modules/.cache清空全局构建缓存后重新启动即可。
报错2修复:Vue版Storybook启动触发webpackFinal阶段属性读取错误
报错特征
执行
yarn storybook:vue时抛出TypeError: Cannot read property '#<Object>' of undefined,错误定位到.vueStorybook/main.js第19行webpackFinal配置执行阶段。
根因
两个问题叠加触发:一是Node.js 12对部分ES新语法支持不完整,二是webpackFinal逻辑未做空值兜底,且配置隔离失效时会加载Preact侧的React相关构建规则,导致Vue loader读取到undefined的配置项。
修复步骤
- 同Preact版配置逻辑,先修改
package.json中Vue版Storybook启动脚本,指定独立配置目录与端口,禁用缓存:{ "scripts": { "storybook:vue": "start-storybook -p 6007 -c .vueStorybook --no-manager-cache" } } - 修改
.vueStorybook/main.js中的webpackFinal逻辑,增加空值兜底,显式清除跨框架的冲突配置:const path = require('path') module.exports = { // 保留原有stories、addons配置 presets: ['@storybook/vue/preset'], configDir: path.resolve(__dirname), webpackFinal: async (config = {}) => { // 初始化配置兜底,避免undefined属性读取错误 config.module = config.module || { rules: [] } config.resolve = config.resolve || { alias: {} } config.module.rules = config.module.rules || [] // 清除误加载的react/preact相关别名,避免构建规则冲突 Object.keys(config.resolve.alias).forEach(aliasKey => { if (['react', 'react-dom', 'preact', 'preact/compat'].includes(aliasKey)) { delete config.resolve.alias[aliasKey] } }) // 原有自定义webpack逻辑(如组件库别名、loader规则)写在此处 config.resolve.alias['@your-vue-ui-lib'] = path.resolve(__dirname, '../dist/vue') config.module.rules.push({ test: /\.vue$/, loader: 'vue-loader' }) return config } } - 如果仓库根目录存在公共babel、postcss配置,在
.vueStorybook、.reactStorybook目录下分别放置独立的配置文件,覆盖根目录规则,避免跨框架语法转译冲突。
通用注意事项
- 两套Storybook必须使用不同的启动端口,避免本地服务缓存串扰
- 每次切换启动不同框架的Storybook前,先清空
node_modules/.cache目录,Storybook默认缓存不会区分不同配置目录的构建产物,极易出现配置串用问题 - 保持两套Storybook的依赖版本一致,避免
@storybook/preact与@storybook/vue版本差过大导致核心模块加载逻辑冲突
内容的提问来源于stack exchange,提问作者UIDev
相关产品推荐
相关产品推荐

