如何使用模块联合的动态遥控器将 React vite 项目配置为微前端方法?

问题描述 投票:0回答:1

我有一个使用react和vite的项目,我使用@module-federation/vite设置了一个微前端方法来获取遥控器,也在遥控器中使用相同的堆栈和配置。现在我想要从模块联合动态遥控器以便能够在运行时加载遥控器。根据模块联合文档,使用此插件是不可能的,但可以使用Federation Runtime来完成。对于主机应用程序来说,这是加载遥控器

import React, { useState, useEffect, Suspense, lazy } from "react";
import { init, loadRemote, registerRemotes } from "@module-federation/enhanced/runtime";
import ErrorBoundary from "../errorBoundary";


init({
  name: "remote",
  remotes: [
    {
      name: "remote",
      entry: "http://localhost:4174/remoteEntry.js",
    },
  ],
});

const useRemote = (scope: string, module: string) => {
  const LazyComponent = lazy(async () => {
    // registerRemotes([
    //   {
    //     name: "remote",
    //     entry: "http://localhost:4174/remoteEntry.js",
    //   },
    //   {
    //     name: "remoteToolbox",
    //     entry: "http://localhost:4175/remoteEntry.js",
    //   },
    // ]);

    return loadRemote<{ default: any }>(`${scope}/${module}`, {
      from: "runtime",
    }) as Promise<{ default: any }>;
  });

  return (props: any) => {
    const [{ module, scope }, setSystem] = useState<any>({});

    const setApp2 = () => {
      setSystem({
        scope: "remote",
        module: "remote-menu",
      });
    };

    const setApp3 = () => {
      setSystem({
        scope: "remoteToolbox",
        module: "remote-toolbox",
      });
    };
    return (
      <div
        style={{
          fontFamily:
            '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
        }}
      >
        <h1>Dynamic System Host</h1>
        <h2>App 1</h2>
        <p>
          The Dynamic System will take advantage of Module Federation{" "}
          <strong>remotes</strong> and <strong>exposes</strong>. It will not
          load components that have already been loaded.
        </p>
        <button onClick={setApp2}>Load App 2 Widget</button>
        <button onClick={setApp3}>Load App 3 Widget</button>
        <div style={{ marginTop: "2em" }}>
          <ErrorBoundary>
            <LazyComponent {...props} />
          </ErrorBoundary>
        </div>
      </div>
    );
  };
};

export default useRemote;

使用远程组件:

function Home() {
    const App = useRemote("remote", "remote-menu");

    return (
      <ErrorBoundary>
        <Suspense>
          <App />
        </Suspense>
      </ErrorBoundary>
    );
  }

主机组件的 vite 配置设置为虚拟远程:

import { fileURLToPath, URL } from "node:url";

import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react";
import { federation } from '@module-federation/vite';

// https://vitejs.dev/config/
export default defineConfig(({ mode }: any) => {
  const selfEnv = loadEnv(mode, process.cwd());
  const remoteSideMenuUrl = selfEnv.VITE_REMOTE_SIDE_MENU_URL;
  const remoteToolboxUrl = selfEnv.VITE_REMOTE_TOOLBOX_URL;
  return {
    server: {
      fs: {
        allow: ['.'],
      },
    },
    build: {
      target: 'esnext', minify: false, cssCodeSplit: false,
      commonjsOptions: {
        include: ["tailwind.config.js", "node_modules/**"],
      },
    },
    optimizeDeps: {
      include: ["tailwind-config"],
    },
    plugins: [
      federation({
        name: 'ShellApp',
        remotes: {
          dummy: "dummy.js",
          // remote: {
          //   type: 'module',
          //   name: 'remote',
          //   entry: remoteSideMenuUrl + '/remoteEntry.js',
          //   entryGlobalName: 'remote',
          //   shareScope: 'default',
          // },
          // remoteToolbox: {
          //   type: 'module',
          //   name: 'remoteToolbox',
          //   entry: remoteToolboxUrl + '/remoteEntry.js',
          //   entryGlobalName: 'remoteToolbox',
          //   shareScope: 'default',
          // },
        },
        exposes: {},
        filename: 'remoteEntry.js',
        //shared: ['react', 'react-dom', 'react-router-dom', "tailwindcss"],
      }),
      react(),
    ],
    resolve: {
      alias: {
        "@": fileURLToPath(new URL("./src", import.meta.url)),
        "tailwind-config": fileURLToPath(
          new URL("./tailwind.config.js", import.meta.url)
        ),
      },
    },
  }
});

这是 vite.conf.ts

import { federation } from '@module-federation/vite';
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';

export default defineConfig(({ mode }) => {
    const selfEnv = loadEnv(mode, process.cwd());
    return {
        base: "./",
        server: {
            fs: {
                allow: ['.'],
            },
        },
        build: {
            target: 'esnext',
        },
        plugins: [
            federation({
                filename: 'remoteEntry.js',
                name: 'remote',
                exposes: {
                    './remote-menu': './src/App.tsx',
                },
                remotes: {},
                shared: ['react', 'react-dom', 'react-router-dom'],
            }),
            react(),
        ],
    };
});

构建在主机中运行良好,但是当我在浏览器中打开应用程序时,出现此错误:

index-DcUMJ190.js:375 Error: [ Federation Runtime ]: Failed to get remoteEntry exports.
args: {"remoteName":"remote","remoteEntryUrl":"http://localhost:4174/remoteEntry.js","remoteEntryKey":"remote"}
https://module-federation.io/guide/troubleshooting/runtime/RUNTIME-001
    at error (ShellApp__mf_v__runtimeInit__mf_v__-B_MJuhnz.js:1086:11)
    at Object.assert (ShellApp__mf_v__runtimeInit__mf_v__-B_MJuhnz.js:1078:9)
    at ShellApp__mf_v__runtimeInit__mf_v__-B_MJuhnz.js:2184:16

Module federation runtime error

我尝试按照此示例存储库更改遥控器和主机中的配置:https://github.com/RussellCanfield/nx-rspack-microfrontend-demo/blob/dynamic-loader/apps/mfe-monorepo/src/app/功能/主页/组件/Home.tsx
但不同的是,我这边有vite。

你们中的一些人尝试过这种动态远程方法吗?

reactjs typescript runtime vite webpack-module-federation
1个回答
0
投票

对于可能需要它的人,这解决了我的问题:

init({
  name: "ShellApp",
  remotes: [
    {
      type: "module",
      name: "remote",
      entry: "http://localhost:4174/remoteEntry.js",
    },
    {
      type: "module",
      name: "remoteToolbox",
      entry: "http://localhost:4175/remoteEntry.js",
    },
  ],
});

https://github.com/module-federation/core/discussions/3252

© www.soinside.com 2019 - 2024. All rights reserved.