自定义React/MUI UI库导入后导致React应用崩溃
问题:React+Material-UI UI库导入Rails应用后渲染失败
开发跨项目复用的React+Material-UI UI库,纯自定义React组件导入Ruby on Rails/React主应用时可正常使用;但当组件引入@mui/material元素后,组件虽能正常导入,启动Web服务器后页面无内容且控制台报错。手动删除主应用node_modules/ui/node_modules可临时解决,但需永久方案避免每次升级/安装库都手动操作。
问题重现代码示例
正常工作的纯React组件
import * as React from 'react'; export const MyComponent: React.FunctionComponent = (() => { return( <> <h1>Hello React</h1> <p>This is an example export of multiple components</p> </> ) })
引入MUI后出现问题的组件
import * as React from 'react'; import Typography from '@mui/material/Typography/Typography'; export const MyComponent: React.FunctionComponent = (() => { return( <> <h1>Hello React</h1> <p>This is an example export of multiple components</p> <Typography variant={'h1'}>HELLO MUI</Typography> </> ) })
相关配置文件
UI库package.json
{ "name": "ui", "version": "1.0.0", "description": "UI Library", "main": "dist/index.js", "files": [ "dist" ], "author": "Jebs", "license": "MIT", "scripts": { "build": "node esbuild.js && tsc" }, "devDependencies": { "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "esbuild": "^0.19.0", "esbuild-node-externals": "^1.8.0", "react": "^18.2.0", "react-dom": "^18.2.0", "typescript": "^5.1.6", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@fontsource/roboto": "^5.0.8", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4" }, "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/material": "^5.14.4", "@mui/icons-material": "^5.14.3", "@fontsource/roboto": "^5.0.8" } }
UI库esbuild.js
const esbuild = require('esbuild'); const { nodeExternalsPlugin } = require('esbuild-node-externals'); esbuild .build({ entryPoints: ['./src/index.tsx'], outfile: 'dist/index.js', bundle: true, minify: true, treeShaking: true, platform: 'browser', format: 'cjs', target: 'es2020', plugins: [nodeExternalsPlugin({ peerDependencies: true })], }) .catch(() => process.exit(1));
主应用package.json
{ "name": "app", "private": "true", "dependencies": { "@hotwired/stimulus": "^3.2.2", "@hotwired/turbo-rails": "^7.3.0", "@types/react": "^18.2.19", "@types/react-dom": "^18.2.7", "esbuild": "^0.19.0", "react": "^18.2.0", "react-dom": "^18.2.0", "typescript": "^5.1.6", "ui": "../../ui", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@fontsource/roboto": "^5.0.8", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4" }, "scripts": { "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=/assets" }, "peerDependencies": { "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" } }
修复说明
- 依赖结构调整:将UI库中MUI相关依赖从
dependencies移至peerDependencies,同时保留在devDependencies中供本地开发使用。这样要求主应用必须安装这些依赖,确保整个项目中只存在一份MUI和React实例,避免重复加载导致的上下文冲突。 - esbuild配置优化:
- 将
platform从node改为browser,匹配前端组件库的构建目标 - 配置
nodeExternalsPlugin的peerDependencies: true,确保所有peer依赖不会被打包进UI库的dist文件,直接引用主应用中的依赖 - 升级
target为现代浏览器支持的版本,提升兼容性
- 将
- 主应用补全依赖:在主应用的
dependencies中添加UI库声明的所有peer依赖,确保运行时能正确加载所需模块。
执行以上修改后,重新构建UI库并在主应用中重新安装依赖,即可解决页面无内容的问题,无需再手动删除嵌套的node_modules文件夹。
内容的提问来源于stack exchange,提问作者Jeremie Bourgeois
相关产品推荐
相关产品推荐

