Невозможно импортировать компонент с помощью material-ui через федерацию модулей webpack
Простой POC, где у нас есть приложение для реагирования
host_ui
как хозяин и
material_components
как пульт.
material_ui
выставляет компонент
NavBar
.
import React from 'react';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
const NavBar = () => {
return (
<AppBar position="static">
<Toolbar>
<IconButton edge="start" color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6">
News
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
);
}
export default NavBar;
Импорт его на хост вызывает ошибку:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
at resolveDispatcher (react.development.js:1476)
at Object.useContext (react.development.js:1484)
at useTheme (useTheme.js:10)
at useStyles (makeStyles.js:237)
at WithStyles(ForwardRef(AppBar)) (withStyles.js:68)
at renderWithHooks (react-dom.development.js:14985)
at updateForwardRef (react-dom.development.js:17044)
at beginWork (react-dom.development.js:19098)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
react-dom.development.js:20085 The above error occurred in the <WithStyles(ForwardRef(AppBar))> component:
at WithStyles(ForwardRef(AppBar)) (webpack://material_components/./node_modules/@material-ui/styles/esm/withStyles/withStyles.js?:61:31)
at NavBar
at Suspense
at div
at App
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
Uncaught Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://reactjs.org/link/crossorigin-error for more information.
at Object.invokeGuardedCallbackDev (react-dom.development.js:4005)
at invokeGuardedCallback (react-dom.development.js:4056)
at beginWork$1 (react-dom.development.js:23959)
at performUnitOfWork (react-dom.development.js:22771)
at workLoopSync (react-dom.development.js:22702)
at renderRootSync (react-dom.development.js:22665)
at performSyncWorkOnRoot (react-dom.development.js:22288)
at eval (react-dom.development.js:11327)
at unstable_runWithPriority (scheduler.development.js:646)
at runWithPriority$1 (react-dom.development.js:11276)
Хотя он отлично работает, если мы используем только html из компонента NavBar. Есть ли что-то еще, что нужно сделать для использования
material-ui
в модульной федерации.
2 ответа
У меня тоже есть эта проблема, это происходит со мной, когда APP1 был с
React=17.0.0
и APP2 был с
React=17.0.2
. По сути, у меня была специальная конфигурация, чтобы позаботиться об этом случае и загрузить новую копию React, но по какой-то причине она не работала правильно с
MUI
.
Это работает для меня, только когда я устанавливаю одну и ту же версию реакции для обоих приложений и устанавливаю эту конфигурацию для обоих приложений в настройках ModuleFedration:
shared: {
react: {
singleton: true,
requiredVersion: deps["react"],
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
}
}
Настройте объединение модулей для вашего навигационного компонента следующим образом:
new ModuleFederationPlugin({
name: "NavApp",
filename: 'remoteEntry.js',
exposes:{
'./NavComponent':'./src/{root of the nav project}'
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
},
},
})
Настройте федерацию модулей для приложения, использующего навигацию, следующим образом:
`new ModuleFederationPlugin({
name: "Appliaction",
remotes: {
NavApp: 'NavApp@http://localhost:{port that is running your Nav
application}/remoteEntry.js',
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
},
},`
Настройте свой пакет навигации следующим образом:
"dependencies": {
"@babel/core": "^7.13.14",
"@babel/preset-react": "^7.13.13",
"add": "^2.0.6",
"babel-loader": "^8.2.2",
"css-loader": "^5.2.0",
"html-webpack-plugin": "^5.3.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"style-loader": "^2.0.0",
"webpack": "^5.30.0",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2",
"yarn": "^1.22.10",
"@emotion/react": "^11.1.5",
"@emotion/styled": "^11.1.5",
"@material-ui/core": "^5.0.0-alpha.28",
"@material-ui/icons": "^5.0.0-alpha.28",
"@material-ui/styles": "^4.10.0",
"@material-ui/system": "^4.11.3",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"serve": "^11.3.0"
}
Не меняйте версию react или react-dom, если у вас есть другие зависимости, добавьте также
Настройте пакет вашего основного приложения (которое использует Nav) следующим образом:
"dependencies": {
"@babel/core": "^7.13.14",
"@babel/preset-react": "^7.13.13",
"babel-loader": "^8.2.2",
"css-loader": "^5.2.0",
"html-webpack-plugin": "^5.3.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"style-loader": "^2.0.0",
"webpack": "^5.30.0",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2",
"@material-ui/core": "^4.9.5",
"@material-ui/icons": "^4.9.1",
"copy-webpack-plugin": "^5.1.1",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"serve": "^11.3.0"
}
Не меняйте версию react или react-dom, если у вас есть другие зависимости, добавьте также
Удалите папку node_modules и удалите файл yarn.lock или package-lock.json из обоих приложений. Из Yarn или Npm снова установите в приложениях (для установки новых зависимостей). После этих изменений все должно работать.