javascript - Webpack 模块联合和 react-router-dom

标签 javascript reactjs react-router react-router-dom webpack-module-federation

如何正确设置 ModuleFederation 和 react-router-dom这样我就可以拥有

  • RouterHost 中定义的路由应用
  • 和远程Header应用有 <Link>指向 Host 中定义的路由的组件?

  • 但是,以下设置失败,出现以下错误:index.js:15 Uncaught Error: useHref() may be used only in the context of a <Router> component.设置:
    主机 mfe 应用程序,本地主机:3001
    ...
    import { BrowserRouter } from 'react-router-dom'
    
    const Header = lazy(() => import("header/Header"))
    
    const Host = () => {
      return (
        <BrowserRouter>
           <React.Suspense fallback="Loading Header...">
             <Header />
           </React.Suspense>
           <Switch>
             <Route path="/input">
               <InputFormView />
             </Route>
             <Route path="/">
                <ListView />
             </Route>
           </Switch>       
        </BrowserRouter>)
    }
    
    ...
    
    
    主机的 webpack.config.js
    
    ...
    
    plugins: [
      new ModuleFederationPlugin({
          name: 'host',
          remotes: {        
            header: 'header@http://localhost:3002/remoteEntry.js'
          },
          exposes: {
          },
          shared: {
            ...deps,
            react: {
              singleton: true,
              requiredVersion: deps.react,
            },
            "react-dom": {
              singleton: true,
              requiredVersion: deps["react-dom"],
            },       
            "react-router-dom": {
              singleton: true,
              requiredVersion: deps["react-router-dom"],
            }
          },
        }),
    ...
    
    header mfe 应用程序,本地主机:3002
    ...
    
    import { Link } from 'react-router-dom'
    
    const Header = () => {
     return (
       <div id="header">
         <h1> Header </h1>
         <Link to="/input"> 
            <button type="button"> Input form </button>        
         </Link>
       </div> 
     )
    
    ...
    
    
    Header 的 webpack.config.js
    
    ...
    
     new ModuleFederationPlugin({
          name: 'header',
          filename: 'remoteEntry.js',
          exposes: {
            './Header': './src/Components/Header'
          },
          remotes: {},      
          shared: {
            ...deps,
            react: {
              singleton: true,
              requiredVersion: deps.react,
            },
            "react-dom": {
              singleton: true,
              requiredVersion: deps["react-dom"],
            },      
            "react-router-dom": {
              singleton: true,
              requiredVersion: deps["react-router-dom"],
            }
          },
        }),
    ...
    
    
    但是,如果我也包装 HeaderBrowserRouter我遇到了以下错误:index.js:15 Uncaught Error: You cannot render a <Router> inside another <Router>. You should never have more than one in your app.

    最佳答案

    在您的远程应用程序中,您应该将 header 组件包装在 BrowserRouter 中,但不应公开包含 BrowserRouter 的组件。在示例中,我使用的是 react-router-dom v6。
    使用另一个组件(在我的示例中是 Test.js,它将在 index.js 中使用,但这不会被模块联合公开,它仅用于远程应用程序的本地开发)。 Header 是您要公开给模块联合并在其他应用程序中使用的组件(因为您已经在 webpack 配置中拥有它)

    import React from 'react';
    import {
        BrowserRouter,
        Routes,
        Route,
      } from "react-router-dom";
    import Header from './Header';
    
    const localRouter = () => {
      return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<div>home<Header></Header></div>}></Route>
                <Route path="input"element={<div>input</div>}/>
            </Routes>
        </BrowserRouter>)
    }
    
    export default localRouter;
    
    然后在您的主机应用程序中,您可以像在远程应用程序中一样使用 Header 组件。
    import React from 'react';
    import {
      BrowserRouter,
      Routes,
      Route,
      Link
    } from "react-router-dom";
    
    const Header = React.lazy(() => import('header/Header'));
    
    const HostApp = () => (
      <>
        <div>Hello, I'm the host app!</div>
        <BrowserRouter>
        <Routes>
            <Route path="/" element={<div>home
                        <React.Suspense fallback="loading...">
                            <Header />
                        </React.Suspense>
                  </div>}></Route>
            <Route path="input"element={<div>input</div>}/>
    
    ... some other routes
    
        </Routes>
      </BrowserRouter>
      </>
    );
    
    export default HostApp;
    
    这个想法是远程应用程序需要 header 在 BrowserRouter 内运行以进行本地开发,但是当在主机应用程序中使用时,Header 组件将使用主机应用程序中的 BrowserRouter,因为来自远程应用程序的 BrowserRouter 不会在任何地方被模块联合。

    关于javascript - Webpack 模块联合和 react-router-dom,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70639472/

    相关文章:

    c# - 在数组中使用命名键 C# MVC razor

    javascript - ionic 3 : How to preload tabs?

    javascript - 来自文本字段的值不返回任何内容

    javascript - Bootstrap 在 React 中不起作用

    reactjs - 如何在 NextJS 中创建轮播?

    node.js - Node React,Action到达后端但不保存产品

    javascript - 如何使用 React 创建多页面应用程序?

    javascript - 为什么react-router setRouteLeaveHook破坏了索引链接?

    Javascript检查字符串中的三个升序字母和数字

    reactjs - React Router 仅在第二次点击后更新