如何将一个Angular应用嵌入到另一个应用中?

38

我的团队开发了一个使用Angular 5的应用程序,已经在生产环境中运行了一段时间,但是最近我们被要求让该应用程序在公司拥有的其他三个站点中运行。其中一个站点是使用Angular6构建的SPA,另一个站点也是SPA,但使用的是Angular5,而另一个站点则使用一些旧的库,如jQuery。

管理层希望我们立即与使用Angular5的SPA集成,因此我们将整个应用程序导出为具有子路由的模块,让其他应用程序进行引导。

但我担心上述方法对于非Angular站点不起作用。这也会将两个应用程序紧密耦合,因为“宿主”应用程序需要知道我们应用程序的所有依赖项,而这并不是一个简单的应用程序(我认为它相当大),并安装它们。当两个应用程序需要同一个依赖项的不同版本时,会出现问题,更不用说我们需要在升级依赖项或框架本身时进行同步。我认为当嵌入应用程序到更多站点时,这种方法不可扩展。

我对于更通用的实现的第一个想法是将我们的应用程序升级到Angular 6并创建一个具有自定义元素的Web组件,但我们需要支持IE11和Edge,它们不支持本机封装,因此我们需要在使用应用程序的每个站点上进行测试,以确保它们不会破坏我们的样式,而且我不知道Web组件是否可以管理子路由。

另一个想法是使用iframe,但我的问题在于iframe如何调整大小以适应内容,并且如何从iframe内的'resident'应用程序向'host'应用程序添加子路由。

有更好的方法来实现我们需要做的事吗?

理想的解决方案应该允许我们的应用程序在多个站点中使用(每个站点提供特定的配置),而不必了解使用我们应用程序的站点。

感谢您的帮助。


应用程序需要在同一URL上吗?它需要与主机应用程序具有相同的样式吗?这是经过身份验证的应用程序吗?它支持SSO吗? - r2018
是的,理想情况下,该应用程序应位于同一URL中,但我们需要控制其中的一部分。例如:这由主应用程序控制 -> companysite.com/myapp,我们的应用程序应该控制子路由:companysite.com/myapp/this/portion/is/ours该应用程序在一个站点中进行身份验证,但其他站点的身份验证是可选的,匿名用户也可以。我们不控制任何站点的身份验证,并且每个站点的身份验证方式都不同,例如在某个站点中它可能是一个cookie,而在另一个站点中它是一个Authorization: Bearer令牌。 - Jorge Rivera
3个回答

45

2020年更新

您还可以使用新的Webpack 5模块联邦

下面的示例展示了如何在Angular和其他技术中使用模块联邦。

原始回答

最近我忙于探讨这个主题,因为很多人一遍又一遍地碰到同样的问题(当然我也是)。现在,您经常听到微前端的概念。该概念旨在设计可扩展和可伸缩的前端。尤其是在许多公司都有AngularReactVue开发人员的时代。

链接

您可以创建新应用程序,并从您的旧应用程序中获得一个超链接。(当切换两个应用程序时,必须重新加载页面。)

IFrames:

一名软件架构师构建了一个元路由来处理iframe和单页应用:

元框架:

元框架允许您在使用不同框架构建的不同应用之间进行通信:
下面是一些用于微前端目的的元框架示例。

Web组件,例如Angular元素:

为了处理npm包,您可以像其他回答者提到的那样使用Angular元素的概念。您需要创建一个外壳应用程序和另一个独立的应用程序,这些应用程序将在您的外壳应用程序中注册为元素。请看这个例子:使用Angular元素构建微前端应用

Mosaiq: 布局服务

在线商店Zalando也面临同样的问题,因此他们创建了一个框架来解决这个问题:

特别是部分Tailor.js,它是一个开源系统,用于在后端层按需组装组件,并由Go编写。

PS. Tailor受到Facebook的BigPipe: Pipelining web pages for high performance启发。

插件架构

插件架构是一种在特定点调用外部代码的架构,而不预先知道该代码的所有细节。

这个Stackoverflow问题更详细地解释了单页应用程序的情况。

Angular库

我认为一个正确的做法是在应用程序中使用相同版本的框架 (例如 Angular 7)。我更倾向于花费时间升级到 Angular 的 TypeScript 版本。希望这个答案对别人有用。

其他相关的 Stackoverflow 问题和回答:

Vue.JS - 微前端方法
微前端架构建议

微前端示例

有关微前端的资源列表

https://github.com/billyjov/microfrontend-resources


14

我认为你的问题的解决方案在于 Angular Elements。它非常棒,由 Angular 团队提供。

Angular Elements 允许您将 Angular 组件打包为自定义 Web 元素,这是 Web 平台 API 的一部分。Web 组件是帮助创建可重用、封装元素的技术。目前,它包括影子 DOM、HTML 模板、HTML 导入和自定义元素。自定义元素技术为Angular Elements 提供动力。

以下是一些参考链接,您可以从中了解更多关于Angular Elements的信息。

https://angular.io/guide/elements

https://www.telerik.com/blogs/getting-started-with-angular-elements

谢谢!


只有Chrome、Safari和Opera原生支持它。详情请见:https://angular.io/guide/elements#browser-support-for-custom-elements - Krishna Mohan
是的,我见过Angular元素的东西,但它在IE11或Edge中不支持本地化。这是一个问题,因为非本地封装允许样式从父应用程序过滤,那么路由呢? - Jorge Rivera
是的,@JorgeRiv说得没错,但是他们正在不断地日复一日地改进它。因此,有很多功能被添加的机会!也许包括路由。 - Shreenil Patel
1
根据文档链接,Angular现在被列为“Edge(基于Chromium的)”原生支持的浏览器。 - Paramvir Singh Karwal

0

我相信Angular 6 Elements将是非Angular应用程序的唯一选择。这是我所知道的唯一允许组件在Angular之外执行的方法。

为了保持样式封装,您可以使用CSS前缀:

:host

在你的组件的 .css 或 .scss 文件中。

如果你可以摆脱非 Angular 的要求,我建议使用 Angular CDK PortalHost 和 DomPortalHost。


1
是的,这将避免样式从元素内部泄漏到外部,但它不能防止外部样式泄漏到组件中,至少非本地封装和IE11和Edge不支持本地封装。 - Jorge Rivera
如何处理路由? - Humble Dolt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接