基于Turborepo+Material UI构建React设计系统的问题
解决Turborepo + MUI + Vite关联时的Emotion重复加载与动态Require错误
操作复现
- 克隆Turborepo设计系统起始仓库后,执行命令安装依赖:
yarn workspace @acme/core add @mui/material @emotion/react @emotion/styled --dev - 在
acme-core/src创建Button.tsx,重导出MUI组件:// Button.tsx export { default as Button, type ButtonProps } from '@mui/material/Button'; - 更新
acme-core/src/index.tsx导出该组件:export { Button, type ButtonProps } from './Button'; - 执行
yarn dev启动后,Storybook控制台出现警告:emotion-react.browser.esm.js:398 You are loading @emotion/react when it is already loaded. Running multiple instances may cause problems. This can happen if multiple versions are used, or if multiple builds of the same version are used. - 创建新Vite React项目,通过
yarn link关联@acme/core,导入组件无TypeScript错误:import { Button } from '@acme/core'; - 但应用崩溃,控制台报错:
index.mjs:12 Uncaught Error: Dynamic require of "react" is not supported at index.mjs:12:9 at ../../node_modules/@emotion/styled/dist/emotion-styled.cjs.dev.js (index.mjs:5938:5) at __require2 (index.mjs:18:49) at ../../node_modules/@emotion/styled/dist/emotion-styled.cjs.js (index.mjs:6097:24) at __require2 (index.mjs:18:49) at index.mjs:6555:29 - 修改
Button.tsx手动引入React后问题依旧:import React from 'react'; import MuiButton, { type ButtonProps as MuiButtonProps } from '@mui/material/Button'; export type ButtonProps = MuiButtonProps; export function Button(props: ButtonProps) { return <MuiButton {...props} />; }
解决方案
1. 修复Emotion重复加载问题
Emotion是运行时必需的依赖,不能放在开发依赖中,同时要强制所有工作区使用同一版本:
# 移除开发依赖并重新添加为生产依赖 yarn workspace @acme/core remove @mui/material @emotion/react @emotion/styled --dev yarn workspace @acme/core add @mui/material @emotion/react @emotion/styled
在Turborepo根目录的package.json中添加resolutions字段,强制依赖版本统一:
"resolutions": { "@emotion/react": "^11.11.0", "@emotion/styled": "^11.11.0" }
执行yarn install重新安装依赖。
2. 修复Vite动态Require错误
Vite不兼容CommonJS的动态require语法,需确保@acme/core输出ES模块:
修改packages/acme-core/tsup.config.ts配置:
import { defineConfig } from 'tsup'; export default defineConfig({ entry: ['src/index.tsx'], format: ['esm'], // 仅输出ES模块格式 dts: true, sourcemap: true, clean: true, external: ['react', 'react-dom'], // 将React标记为外部依赖,避免打包进库 });
重新打包@acme/core:
yarn workspace @acme/core build
同时在Vite项目的vite.config.ts中添加优化配置:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], optimizeDeps: { include: ['@acme/core'], }, resolve: { alias: { // 确保React依赖全局统一 'react': require.resolve('react'), 'react-dom': require.resolve('react-dom'), }, }, });
重启Vite项目即可恢复正常。
原因分析
- Emotion重复加载:误将运行时依赖设为开发依赖,导致宿主项目和
@acme/core各自安装了Emotion实例;未统一版本加剧了冲突。 - 动态Require错误:
@acme/core默认打包输出包含CommonJS格式,Vite无法处理其中的动态require语法,转为ES模块输出即可解决。
内容的提问来源于stack exchange,提问作者Ioannis Potouridis
相关产品推荐
相关产品推荐

