如何在一个Angular应用程序中加载另一个Angular应用程序

5

我有两个Angular应用程序,分别为A和B。现在在B应用程序的一个标签页中,我想要加载整个应用程序A。我该如何实现?

请告诉我如何实现此功能。Angular是否有任何特殊标记可供使用?

3个回答

5
您的问题的一个解决方案可能是自己创建您所要求的标签。我通过一种名为Web组件或 Angular elements 的技术在Angular应用程序B中实现了Angular应用程序A,如上所述,请参见例如https://www.techiediaries.com/angular/angular-9-elements-web-components/
在以下步骤中,在应用程序A中定义了一个标签shiny-app-a,然后通过将A的JavaScript文件导入B并通过该标签引用它们,在应用程序B中使用该标签。
它适用于以下环境:
  • Angular CLI: 11.0.2
  • Node: 12.16.1
  • OS: win32 x64
使其运行的步骤如下:

1. 创建应用程序A

此应用程序还需要@angular / elements包。

1.1. 创建应用程序A的框架

$ ng new App-A
$ cd  App-A
$ ng add @angular/elements

1.2. 将更改应用到 app.modules.ts 中,以创建 Web 组件 / 元素并定义相应的标记 shiny-app-a

我的 app.modules.ts 如下所示:

import { BrowserModule } from '@angular/platform-browser';
// import Injector
import { Injector, NgModule } from '@angular/core';
// import createCustomElement
import { createCustomElement } from '@angular/elements';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
  AppComponent
  ],
  imports: [
  BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {

  constructor(private injector: Injector){}

  ngDoBootstrap(){
    const el = createCustomElement(AppComponent, {injector:this.injector});
    // Here you define your new tag shiny-app-a
    customElements.define('shiny-app-a', el);
  }
 }

1.3. 构建项目

$ ng build --prod --output-hashing none

这将生成包括以下文件:
  • runtime.js
  • main.js
  • polyfills.js
你会在文件夹[...] \ App-A \ dist \ App-A中找到它们。

1.4. 测试

运行

$ ng serve

在浏览器中查看您新构建的应用程序A。

2. 创建应用程序B

注意:此处不需要@angular/elements。

2.1. 创建应用程序B的框架

$ ng new App-B

2.2. 将应用程序A的文件复制到应用程序B可访问的文件夹中

在本例中,我使用文件夹[...]/src/assets。

$ cd App-B/src/assets/

将应用程序A中的JavaScript复制到此文件夹中,即:
  • [...]/App-A/dist/App-A/main.js
  • [...]/App-A/dist/App-A/polyfills.js
  • [...]/App-A/dist/App-A/runtime.js

2.3. 将应用程序B的源代码适应步骤1中定义的标签

2.3.1 在app.module.ts中让自定义元素为应用程序B所知

实施的关键项目是CUSTOM_ELEMENTS_SCHEMA。 我的应用程序B的 app.modules.ts 如下所示:

import { BrowserModule } from '@angular/platform-browser';
// import CUSTOM_ELEMENTS_SCHEMA
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  // add schemas
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
2.3.2 在 app.component.ts 中从外部源加载 JavaScript

JavaScript 文件也可以从任何源加载。在这种情况下,文件将通过 OnInit() 从 [..]/assets 文件夹中加载。因此,我的应用程序 B 的 app.component.ts 如下所示:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'App-B';

  ngOnInit() {
    this.loadScript('/assets/runtime.js');
    this.loadScript('/assets/main.js');
    this.loadScript('/assets/polyfills.js');
  }

  public loadScript(url: string) {
    const body = <HTMLDivElement> document.body;
    const script = document.createElement('script');
    script.innerHTML = '';
    script.src = url;
    script.async = false;
    script.defer = true;
    body.appendChild(script);
  }
}
2.3.3 在 app.component.html 中使用标签

将文件 app.component.html 中的任何内容替换为以下内容:

<shiny-app-a></shiny-app-a>

2.4. 测试它

运行

$ ng serve

在应用程序B中查看应用程序A,并在浏览器中查看。

1
这对我部分有效。我将展示第二个Angular应用程序的组件,但它是全屏的,所以我无法显示基本应用程序。我该如何解决? - Elikill58
我遇到了编译器报错:找不到“app-root”元素。我尝试使用前缀甚至更改主项目中的应用程序根元素,但问题仍然存在... :/ - Johana Lopez 1327

2
您希望实现类似微前端的功能,可以将应用程序A构建为Angular自定义元素(Web组件 - Angular Elements),输出会生成一个脚本。在应用程序B中加载这个脚本,并在Micro App B中放置您在创建自定义元素时提供的选择器,以便在任何需要加载App A的地方进行加载。
如果想了解更多关于微前端的内容,请阅读有关Angular Elements的详细资料(Angular Elements)。请不要使用iframe,因为它们很难管理。如果想了解更多信息,请阅读关于Angular微前端的相关博客。

在这个例子中,他们只是加载了一个组件。我想要在另一个应用程序中加载整个应用程序。 - user2900572
Angular Element 不仅仅是一个组件,它是一个封装为组件的完整应用程序。 - Akshay Rajput

0
如Akshay所提到的,您可以使用Angular Elements将应用程序A公开为自定义元素,并在应用程序B中使用它。
在您的情况下,您想将AppComponent公开为自定义元素。

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