В настоящее время я работаю над проектом, который размещается на сервере клиентов. Для новых "модулей" нет намерения перекомпилировать все приложение. Тем не менее, клиент хочет обновить модули маршрутизатора/лени, загруженные во время выполнения. Я пробовал несколько вещей, но я не могу заставить его работать. Мне было интересно, знает ли кто-нибудь из вас, что я еще могу попробовать или что я пропустил.
Одна вещь, которую я заметил, большинство ресурсов, которые я пробовал, используя угловые cli, встраивается в отдельные куски по webpack по умолчанию при создании приложения. Это кажется логичным, поскольку он использует расщепление кода webpack. но что, если модуль еще не известен во время компиляции (но скомпилированный модуль хранится где-то на сервере)? Сборка не работает, потому что не может найти модуль для импорта. И использование SystemJS будет загружать модули UMD всякий раз, когда они будут найдены в системе, но также поставляются в отдельном блоке с помощью webpack.
Некоторые ресурсы, которые я уже пробовал;
- динамический удаленный компонент-загрузчик
- Модуль заряжания
- Загрузка модулей с разных серверов во время выполнения
- Как загрузить динамические внешние компоненты в угловое приложение
- Внедрение архитектуры плагинов/системы плагинов/сменных фреймов в Angular 2, 4, 5, 6
- Угловые 5 - модули нагрузки (которые не известны во время компиляции) динамически во время выполнения
- https://medium.com/@nikolasleblanc/building-an-angular-4-component-library-with-the-angular-cli-and-ng-packagr-53b2ade0701e
- Некоторые другие, связанные с этой темой.
Некоторый код, который я уже пробовал и реализую, но не работаю в это время;
Расширение маршрутизатора с помощью обычного файла module.ts
this.router.config.push({
path: "external",
loadChildren: () =>
System.import("./module/external.module").then(
module => module["ExternalModule"],
() => {
throw { loadChunkError: true };
}
)
});
Normal SystemJS Импорт пакета UMD
System.import("./external/bundles/external.umd.js").then(modules => {
console.log(modules);
this.compiler.compileModuleAndAllComponentsAsync(modules['External']).then(compiled => {
const m = compiled.ngModuleFactory.create(this.injector);
const factory = compiled.componentFactories[0];
const cmp = factory.create(this.injector, [], null, m);
});
});
Импортируйте внешний модуль, не работая с webpack (afaik)
const url = 'https://gist.githubusercontent.com/dianadujing/a7bbbf191349182e1d459286dba0282f/raw/c23281f8c5fabb10ab9d144489316919e4233d11/app.module.ts';
const importer = (url:any) => Observable.fromPromise(System.import(url));
console.log('importer:', importer);
importer(url)
.subscribe((modules) => {
console.log('modules:', modules, modules['AppModule']);
this.cfr = this.compiler.compileModuleAndAllComponentsSync(modules['AppModule']);
console.log(this.cfr,',', this.cfr.componentFactories[0]);
this.external.createComponent(this.cfr.componentFactories[0], 0);
});
Использовать SystemJsNgModuleLoader
this.loader.load('app/lazy/lazy.module#LazyModule').then((moduleFactory: NgModuleFactory<any>) => {
console.log(moduleFactory);
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
});
Пробовал загрузку модуля, сделанного с помощью накопителя
this.http.get('./myplugin/${metadataFileName}')
.map(res => res.json())
.map((metadata: PluginMetadata) => {
// create the element to load in the module and factories
const script = document.createElement('script');
script.src = './myplugin/${factoryFileName}';
script.onload = () => {
//rollup builds the bundle so it attached to the window object when loaded in
const moduleFactory: NgModuleFactory<any> = window[metadata.name][metadata.moduleName + factorySuffix];
const moduleRef = moduleFactory.create(this.injector);
//use the entry point token to grab the component type that we should be rendering
const compType = moduleRef.injector.get(pluginEntryPointToken);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(compType);
// Works perfectly in debug, but when building for production it returns an error 'cannot find name Component of undefined'
// Not getting it to work with the router module.
}
document.head.appendChild(script);
}).subscribe();
Пример с SystemJsNgModuleLoader работает только тогда, когда модуль уже предоставляется как "ленивый" маршрут в RouterModule приложения (который превращает его в кусок при построении с помощью webpack)
Я нашел много дискуссий по этой теме в StackOverflow здесь и там, и при условии, что решения действительно хороши для загрузки модулей/компонентов динамически, если они известны заранее. но ни один из них не подходит для нашего варианта использования проекта. Пожалуйста, дайте мне знать, что я еще могу попробовать или погрузиться.
Спасибо!
EDIT: Я нашел; https://github.com/kirjs/angular-dynamic-module-loading и попробует это.
UPDATE: я создал репозиторий с примером загрузки модулей динамически с помощью SystemJS (и используя Angular 6); https://github.com/lmeijdam/angular-umd-dynamic-example