В настоящее время я работаю над проектом, который размещается на клиентском сервере. Для новых «модулей» нет намерения перекомпилировать всего приложения. Тем не менее, клиент хочет обновить маршрутизатор / лениво загруженные модули во время выполнения . Я перепробовал несколько вещей, но не могу заставить его работать. Мне было интересно, знает ли кто-нибудь из вас, что я еще могу попробовать или что я пропустил.
Одна вещь, которую я заметил, большинство ресурсов, которые я пробовал, используя angular cli, по умолчанию при сборке приложения объединяются в отдельные куски с помощью веб-пакета. Что кажется логичным, поскольку использует разделение кода веб-пакета. но что, если модуль еще не известен во время компиляции (но скомпилированный модуль хранится где-то на сервере)? Связывание не работает, потому что он не может найти модуль для импорта. А использование SystemJS будет загружать модули UMD всякий раз, когда они обнаруживаются в системе, но также объединяются в отдельный блок с помощью веб-пакета.
Некоторые ресурсы, которые я уже пробовал;
Некоторый код, который я уже попробовал и реализовал, но в настоящее время не работает;
Расширение роутера обычным файлом module.ts
this.router.config.push({
path: "external",
loadChildren: () =>
System.import("./module/external.module").then(
module => module["ExternalModule"],
() => {
throw { loadChunkError: true };
}
)
});
Обычный 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);
});
});
Импорт внешнего модуля, не работающего с веб-пакетом (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's 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 приложения (который превращает его в чанк при сборке с веб-пакетом)
Я нашел много обсуждений по этой теме в StackOverflow тут и там, и при условии, что решения кажутся действительно хорошими для динамической загрузки модулей / компонентов, если они известны заранее. но ни один не подходит для нашего варианта использования проекта. Пожалуйста, дайте мне знать, что я еще могу попробовать или погрузиться.
Спасибо!
РЕДАКТИРОВАТЬ: я нашел; https://github.com/kirjs/angular-dynamic-module-loading и попробую.
ОБНОВЛЕНИЕ: Я создал репозиторий с примером динамической загрузки модулей с использованием SystemJS (и с использованием Angular 6); https://github.com/lmeijdam/angular-umd-dynamic-example