Как загрузить динамические внешние компоненты в приложение 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.