Angular Приложение динамически загружает плагин без перекомпиляции - PullRequest
2 голосов
/ 05 марта 2020

Я пытаюсь разработать интерфейс моего подключаемого приложения Web Api (NET CORE). Я хотел бы использовать Angular 9, но я не являюсь экспертом в angular.

Мой бэкэнд был разработан для расширения и при запуске он просматривает в указанной папке и, если существует один или несколько файлов DLL, которые содержит лог c для расширения базового приложения (например, плагин), он загружает их. Я хочу использовать аналогичный подход во внешнем интерфейсе. Я пробовал разные решения и читал много статей, но сложно найти кого-то, кто хочет импортировать неизвестный плагин во время компиляции.

Я пробовал ленивые модули (начиная с этого: https://www.mokkapps.de/blog/manually-lazy-load-modules-and-components-in-angular/ ) это было бы идеально, но, используя это, я должен знать реализованный плагин (модули) перед компиляцией моего angular приложения, потому что если я хочу использовать модули, я должен использовать функцию импорта в моем основном приложении.

Так Я искал больше и после статьи Динамически загружать новые модули во время выполнения с Angular CLI & Angular 5 Я попробовал подход System. Js, но я не могу найти работающее решение для angular 9.

Я совершенно уверен, что я не единственный, кто создал бы подключаемое Angular приложение, которое загружает плагины без перекомпиляции основного приложения.

Мне нужно кое-что предложить правильный подход или рабочий пример приложения angular, использующего архитектуру плагинов.

1 Ответ

0 голосов
/ 04 апреля 2020

Я не уверен, что это лучшее и элегантное решение, потому что я новичок ie в Angular, но на данный момент оно работает для меня.

Я предполагаю, что плагин является Элемент веб-компонента (https://angular.io/guide/elements). Чтобы создать свой первый элемент (плагин), я следовал этому уроку: https://www.techiediaries.com/angular/angular-9-elements-web-components/.

Кстати, на данный момент я не могу загружать свои плагины динамически, потому что я должен знать имя компонента, которое Я развернул в своем элементе, прежде чем скомпилировать проект, чтобы использовать его. Я нашел решение, используя элемент Extensions (https://angular-extensions.github.io/elements/# / home ). Итак, я создал динамический c компонент, который я использую для отображения компонента плагина во время выполнения.

Это код динамического c компонента:

export class DynamicComponentContainerComponent implements OnInit {
  plugin: Plugin
  sub: any;

  constructor(private route: ActivatedRoute, private pluginService: PluginService) { }

  ngOnInit() {
    this.sub = this.route
      .data
        .subscribe(data => {
           this.pluginService.getPlugin(data['pluginName'])
            .subscribe(
              (res) => {
                this.plugin = res;
              },
              (err) => {
                console.error(err)
              } 
            );
          });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }
}

И его html template:

<div *ngIf="plugin != null">
<ng-template #loading>Loading plugin {{plugin.tag}} ...</ng-template>
<ng-template #error>Error Loading plugin {{plugin.tag}}</ng-template>
<ax-lazy-element
    *axLazyElementDynamic="plugin.tag; url: plugin.url; module: plugin.isModule; 
errorTemplate: error; loadingTemplate: loading;">
</ax-lazy-element>
</div>

Это может работать, потому что мой бэкэнд обслуживает скомпилированный файл плагина JS (Element Web Component), поэтому мне пришлось зарегистрировать свой плагин (потому что мне нужны некоторые значения для его обработки, такие как имя компонента или путь маршрута) перед его использованием. Фактически, атрибуту axLazyElementDynami c в компоненте dynamici c требуется URL-адрес файла веб-компонента JS Element и имя компонента для работы.

Теперь мне пришлось динамически добавлять пути маршрутов к каждому компоненту плагина. В своем компоненте приложения я создал этот простой метод:

loadPlugins() {
  this.pluginService.getPlugins()
    .subscribe(plugins => {
      plugins.forEach(plugin => {
        this.router.config.unshift({ path: plugin.path, component: 
DynamicComponentContainerComponent, data: { pluginName: plugin.name } });
        this.links.push({ text: plugin.description, path: plugin.path });
      });
    });
}

Служба плагинов просто получает данные о плагинах из бэкэнда (где я ранее регистрировал плагины).

Надеюсь, это кому-нибудь поможет.

...