如何解决微前端中具有相同导入的组件
我正在使用来自 webpack 5 的 ModuleFederationPlugin ModuleFederationPlugin 构建基于微前端的 React 应用程序。
我有两个独立的项目(App1 和 App2),它们公开了组件,它们在其他项目(AppShell)中使用。
App1 结构:
components/Button.tsx
App1.tsx
App2 结构:
components/Button.tsx
App2.tsx
两个项目都包含组件 Button.tsx,这意味着在两个项目中该组件具有相同的导出。该组件在App1.tsx(App2.tsx)中使用。
现在如果我想在 AppShell 中使用 App1 和 App2,我总是看到 App1 中的 Button:
App1 webpack 配置(App2 类似):
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
entry: "./src/index.tsx",output: {
filename: "test-app1.[contenthash].js",},resolve: {
extensions: ['.ts','.tsx','.js','.json'],module: {
rules: [
{
test: /\.(ts|js)x?$/,exclude: /node_modules/,loader: 'babel-loader',],plugins: [
new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './public/index.html'}),new ModuleFederationPlugin({
name: "remoteApp",library: { type: "var",name: "remoteApp" },filename: "remoteEntry.js",exposes: {
"./MyApp": "./src/MyApp",shared: ["react","react-dom","@material-ui/core"],})
]};
AppShell webpack 配置:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
entry: "./src/index.tsx",output: {
filename: "app_shell.[contenthash].js",path: path.resolve(__dirname,"dist"),publicPath: ""
},{
test: /bootstrap\.js$/,loader: "bundle-loader",options: {
lazy: true,new ModuleFederationPlugin({
name: "app_shell",remotes: {
"remoteApp-mfe": "remoteApp@http://localhost:8001/remoteEntry.js","remoteApp2-mfe": "remoteApp2@http://localhost:8002/remoteEntry.js",shared: {react: {singleton: true},"react-dom": {singleton: true},"@material-ui/core": {singleton: true}},}),]};
AppShell 中的组件使用:
import React from "react";
export const AppShell: React.FC = () => {
// @ts-ignore
const App1 = React.lazy(() => import("remoteApp-mfe/MyApp"));
// @ts-ignore
const App2 = React.lazy(() => import("remoteApp2-mfe/MyApp2"));
return (
<>
<h1>App Shell</h1>
<React.Suspense fallback="Loading...">
<App1 />
</React.Suspense>
<React.Suspense fallback="Loading...">
<App2 />
</React.Suspense>
</>
);
};
您可以下载测试应用程序 here。
请问您知道如何解决这个问题吗? (我知道我可以重构应用程序,但这不是我正在寻找的解决方案;))。 谢谢。
解决方法
错误在于您的各个应用程序的包名称。应用文件夹中的每个 package.json 都具有名称 "test"
:
app-shell/
public/
src/
package.json -> package name = "test"
...
test-app-01/
public/
src/
package.json -> package name = "test"
...
test-app-02/
public/
src/
package.json -> package name = "test"
...
当您的应用程序在客户端拼接在一起时,来自所有 3 个包的所有应用程序代码都会合并到同一范围 "test"
下。现在出现问题是因为应用程序具有部分相同的文件夹和文件结构。
test-app-01/
public/
src/
components/
MyButton.tsx
// other code
...
test-app-02/
public/
src/
components/
MyButton.tsx
// other code
...
由于客户端在相同范围 "test"
下的合并,按钮代码被两个 test-apps
之一覆盖,如下所示:
test/
src/
components/
MyButton.tsx // MyButton.tsx from test-app-01 or test-app-02 gets overridden
// other code of app-shell,test-app-01 and test-app-02.
解决方案是在 package.json 中为所有应用程序提供单独的包名称。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。