Как загрузить динамические внешние компоненты в приложение Angular

У меня проблема с применением Angular.

Я хотел бы, чтобы угловое приложение было написано в сборке Typscript с (aot).

Цель состоит в том, чтобы отобразить панель пользователя с некоторыми виджетами. Виджет - это угловой компонент.

Мое приложение поставляется с некоторыми встроенными виджетами. Но виджеты должны быть расширены чем-то вроде рынка; или созданный вручную.

Маркет должен скачивать файлы (js/ts/bunlde..??) в определенную папку.

Тогда мое приложение должно иметь возможность загружать новые виджеты (= компонент ng) и создавать их экземпляры.

Структура моей папки (производство)

  |- index.html
  |- main.f5b448e73f5a1f3f796e.bundle.js
  |- main.f5b448e73f5a1f3f796e.bundle.js.map
  |- .... (all other files generated)
  |- externalWidgets
      |- widgetA
            |- widjetA.js
            |- widjetA.js.map
            |- assets
                 |- image.png
      |- widgetB
            |- widjetB.ts
            |- widjetB.html
            |- widjetB.css

Затем при загрузке пользовательской страницы в базе данных говорят, что есть виджет A. Таким образом, цель состоит в том, чтобы динамически загружать файлы и создавать экземпляр включенного компонента.

Я перепробовал много решений, использующих "require" и "System.import", но оба они терпят неудачу, когда путь к загрузке генерируется динамически.

Это должно быть возможно? Я могу изменить свою структуру кода; изменить внешние виджеты.. (например, widgetB еще не передан,...)

На самом деле я ищу "систему плагинов" с приложением Angular4/webpack.

1 ответ

Решение

Я делаю точно так же. И я объясняю детали в этом выступлении на NgConf.

Первое, что нужно понять, это то, что Webpack не может динамически загружать модули, которые неизвестны во время сборки. Это присуще тому, как Webpack строит дерево зависимостей и собирает идентификаторы модулей во время сборки. И это прекрасно, так как Webpack - это пакет модулей, а не загрузчик модулей. Таким образом, вам нужно использовать загрузчик модулей, и теперь единственной приемлемой опцией является SystemJS.

Затем каждый плагин должен быть упакован как модуль, а все экспортированные компоненты должны быть добавлены в entryComponents этого модуля.

Во время выполнения вы загрузите этот модуль, чтобы получить доступ к компонентам, объявленным внутри него. Вам действительно не нужен модуль, но это единица упаковки в Angular, поэтому вы не можете избежать его использования. Теперь, когда вы получите модуль, вам придется выбирать опции в зависимости от того, построен ли модуль с использованием AOT или нет.

Если он построен с использованием AOT, вы просто получаете экспортированный класс фабрики из модуля и создаете экземпляр модуля:

System.import('path/to/module').then((module)=>{
    const moduleFactory = module.moduleFactoryClassName;
    const moduleRef = moduleFactory.create(this.parentInjector);
    const resolver = moduleRef.componentFactoryResolver;
    const compFactory = resolver.resolveComponentFactory(AComponent);
}

Если он не построен с использованием AOT, вы должны скомпилировать его с помощью JIT-компилятора:

System.import('path/to/module').then((module)=>{
    const moduleFactory = this.compiler.compileModuleSync(module.moduleClassName);
    const moduleRef = moduleFactory.create(this.parentInjector);
    const resolver = moduleRef.componentFactoryResolver;
    const compFactory = resolver.resolveComponentFactory(AComponent);
}

Затем вы можете добавлять динамические компоненты куда угодно, используя методы, описанные в этой статье: Вот что вам нужно знать о динамических компонентах в Angular.

Другие вопросы по тегам