微前端中具有相同导入的组件

如何解决微前端中具有相同导入的组件

我正在使用来自 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:

enter image description here

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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?