2

我正在尝试使用模块联合构建一个 vue js 2 微前端。我不想像这样通过 webpack.config.js 使用静态远程导入

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      remotes: {
        app1: 'app1@http://localhost:3001/remoteEntry.js',
      },
    }),
  ],
};

我正在寻找一种将 vue 组件动态导入我的主机应用程序的方法。到目前为止,我尝试了这种方法,但我只找到了适用于 angular 或 react 的示例。

目标是拥有多个远程前端,可以在某处自动注册,也许在某种商店中。然后主机应用程序可以访问这个存储并获取所有已注册的远程应用程序(名称、url、组件)。宿主应用程序然后加载组件并且应该能够使用它们。我远程导入组件 HelloDerp,加载过程工作正常,但我不知道如何在我的主机应用程序上呈现它。我阅读了关于动态和异步导入的 vue js 文档,但我认为这只适用于本地组件。到目前为止,我在主机应用程序中得到了什么:

<template>
  <div id="app">
    <HelloWorld />
    <HelloDerp />
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";
const HelloDerp = null;


export default {
  name: "App",
  components: {
    HelloWorld,
    HelloDerp,
  },
  mounted() {
    var remoteUrlWithVersion = "http://localhost:9000/remoteEntry.js";
    const element = document.createElement("script");

    element.type = "text/javascript";
    element.async = true;
    element.src = remoteUrlWithVersion;
    element.onload = () => {
      console.log(`Dynamic Script Loaded: ${element.src}`);
      HelloDerp = loadComponent("core", "./HelloDerp");
    };

    document.head.appendChild(element);

    return null;
  },
};

async function loadComponent(scope, module) {
  // Initializes the shared scope. Fills it with known provided modules from this build and all remotes
  await __webpack_init_sharing__("default");
  const container = window[scope]; // or get the container somewhere else
  // Initialize the container, it may provide shared modules
  await container.init(__webpack_share_scopes__.default);
  const factory = await window[scope].get(module);
  const Module = factory();
  return Module;
}
</script>
4

1 回答 1

0

抱歉,我差点忘了这件事。这是我的解决方案。

加载模块:

export default async function loadModules(
  host: string,
  ownModuleName: string,
  wantedNames: string[]
): Promise<RemoteComponent[]> {
    ...
    uiApplications.forEach((uiApplication) => {
      const remoteURL = `${uiApplication.protocol}://${uiApplication.host}:${uiApplication.port}/${uiApplication.moduleName}/${uiApplication.fileName}`;

      const { componentNames } = uiApplication;
      const { moduleName } = uiApplication;
      const element = document.createElement('script');
      element.type = 'text/javascript';
      element.async = true;
      element.src = remoteURL;

      element.onload = () => {
        componentNames?.forEach((componentName) => {
          const component = loadModule(moduleName, `./${componentName}`);

          component.then((result) => {
            if (componentName.toLowerCase().endsWith('view')) { 
            // share views
              components.push(new RemoteComponent(result.default, componentName));
            } else { 
            // share business logic
              components.push(new RemoteComponent(result, componentName));
            }
           });
        });
      };
      document.head.appendChild(element);
    });
  });
  ...
}

export default async function loadModule(scope: string, module: string): Promise<any> {
  await __webpack_init_sharing__('default');
  const container = window[scope]; // or get the container somewhere else
  await container.init(__webpack_share_scopes__.default);
  const factory = await window[scope].get(module);
  const Module = factory();
  return Module;
}

将模块添加到路由

 router.addRoute({
        name: remoteComponent.componentName,
        path: `/${remoteComponent.componentName}`,
        component: remoteComponent.component,
  });
于 2022-02-09T10:20:42.537 回答