目前,我正在研究一个托管在客户端服务器上的项目。对于新的“模块”,无意重新编译整个应用程序。也就是说,客户端希望在运行时更新路由器/延迟加载的模块。我已经尝试了几种方法,但是无法正常工作。我想知道你们中的任何人知道我仍然可以尝试还是错过了什么。
我注意到的一件事是,在构建应用程序时,默认情况下,我尝试使用angular cli尝试的大多数资源都由webpack捆绑为单独的块。这似乎很合理,因为它利用了webpack代码拆分。但是,如果在编译时尚不知道该模块(但是已编译的模块存储在服务器上的某个位置),该怎么办?绑定不起作用,因为它找不到要导入的模块。使用SystemJS可以在系统上找到时加载UMD模块,但也可以通过webpack捆绑到单独的块中。
我已经尝试过的一些资源;
- 动态远程组件加载器
- 模块加载
- 在运行时从其他服务器加载模块
- 如何将动态外部组件加载到Angular应用程序中
- 在Angular 2、4、5、6中实现插件架构/插件系统/可插入框架
- Angular 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 };
}
)
});
UMD捆绑包的普通SystemJS导入
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'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中已将模块作为“惰性”路由提供时才起作用(使用webpack构建时将其转换为大块)
我在这里和那里的StackOverflow上找到了很多有关此主题的讨论,并且提供了动态加载模块/组件的解决方案(如果事先知道的话)看起来真的很不错。但没有一个适合我们的项目用例。请让我知道我仍然可以尝试或尝试的内容。
谢谢!
编辑:我发现;https://github.com/kirjs/angular-dynamic-module-loading,然后尝试一下。
更新:我创建了一个存储库,并带有使用SystemJS(和Angular 6)动态加载模块的示例;https://github.com/lmeijdam/angular-umd-dynamic-example
我相信,如果您使用webpack构建和运行主应用程序,则可以使用SystemJS来加载UMD捆绑包。我使用了使用ng-packagr构建动态插件/附加模块的UMD捆绑包的解决方案。这个github演示了描述的过程:https : //github.com/nmarra/dynamic-module-loading