具有动态导入的主机应用程序

Host application with dynamic imports

我有一个带有 Parent 组件和多个 children 的 React 应用程序。 每个 children 代表一个带有清单的不同应用程序。

src/
   host/ 
        Host.js
   app/
        foo/ 
            Foo.js
            manifest.json
        bar/ 
            Bar.js
            manifest.json 
        baz/
            Baz.js
            manifest.json  

我想在每个应用程序中包含一些重要的应用程序数据(如路线名称) 应用程序清单并让主机应用程序读取它们。

{
    "name": "Foo",
    "location": "this/is/a/foo/route"
}

主机应该能够使用路由器导航到使用 manifest.location.

里面的数据

我想避免在主机中维护当前应用程序的列表 所以代码尽可能可重用。

我在想的是做某种 Webpack 进程来识别路径 清单,然后动态生成这些导入。

我不知道我提出的解决方案是否可行。 有没有更好的方法来使用 Webpack 实现这种功能? 你能给我指出正确的方向吗?

谢谢。

对您的方法的一些想法:

I want to have some important application data (like the route name) in each application manifest and having the host application read them.

为什么 child 应用程序必须了解其在 manifest.json 中的路由器配置?您的主机应用程序负责编排所有 children 应用程序。它是一个,它应该知道路由到特定 child 应用程序的映射。

更详细一点:可能有一个原因,为什么你首先隔离了 child 个应用程序 - 它们 self-sufficient 并且彼此独立,也独立于主机.例如。想象一下,您可能想要重复使用其中一个应用程序并将它们 运行 作为 stand-alone 应用程序。这也是为什么让 children 在主机中注册自己的另一种方式并不理想的原因。因为这会在 child 和主机之间强制执行更紧密的耦合 - child 必须知道,它在一些更大的应用程序中使用。

Child 应用

关于 child 应用程序,它可以只导出一些 运行nable 回调,如果路由匹配,主机将调用该回调。在您使用 React 的情况下,导出将由主机呈现的 ReactElement 就足够了。这个入口点也可以用 Webpack 以捆绑过程的形式创建。

// as ReactElement
export const FooChildElement = <div>I am Foo child</div>
// as Component
export const FooChildComp = () => <div>I am Foo child</div>

编排 children 应用程序

I would like to avoid having to maintain a list of the current apps in the Host so the code it's as reusable as possible.

除了了解所有 children 应用程序和路由器配置的主机层之外,您还可以创建一个单独的编排层。它可以提供地图 route -> Runnable child app entry point。主机读取该映射并将其注入其路由器,有效地从知道当前使用的应用程序列表中解脱出来。尽管如此,它仍然对 children 应用程序具有一些传递依赖性/import,以便 运行 它们。您应该问问自己,是否有必要将主机与编排分开。正如您所说,您 可以 在构建过程 (Webpack) 中动态创建导入,但为什么不在项目的一个特定位置硬连接这种关系作为普通 JavaScript object?

export const routeToChildMapping = {
  "this/is/a/foo/route": {
    name: "foo",
    entry: FooChildElement 
  },
  "this/is/a/bar/route" : { ... }
}

主持人

有了这个,主机只知道导出的映射,运行如果路由匹配,应用程序会执行一些错误处理和其他信封任务。

const Router = ({route}) => routeToChildMapping[route].entry

// here getUrlSomewhere simplified
const MyHostApp = () => <Router route={getUrlSomewhere()}/>

我试图简化大局并服从 KISS 在这里,因为一开始不要把事情搞得太复杂是件好事。当然,这在很大程度上取决于您的构建环境和项目。因此,请随意根据您的 needs/requirements!

调整该概念