簡體   English   中英

加載動態組件時出現Angular 4 AOT編譯錯誤:未加載運行時編譯器

[英]Angular 4 AOT Compilation Error while loading a Dynamic Component: Runtime compiler is not loaded

我的Angular應用程序必須處理加載動態組件。 使用JIT ng serve or, ng build編譯,一切正常。 即使使用AOT ng serve --prod or, ng build --prod ,我仍然可以成功進行構建。 另外,應用程序中的所有延遲加載模塊均按預期工作。 但是一旦initiate an event to load a dynamic component從登錄頁面initiate an event to load a dynamic component ,就會出現以下錯誤:

vendor.fbd3ddffb0a9e35bbf55.bundle.js:1 ERROR Error: Uncaught (in promise): 
Error: Runtime compiler is not loaded
Error: Runtime compiler is not loaded
at Z (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at t.compileModuleAndAllComponentsAsync 
(vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at dynamic.module.3b05550d9afcedd58855.chunk.js:1
at t.invoke (polyfills.a58272fc2ef255219061.bundle.js:1)
at Object.onInvoke (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at t.invoke (polyfills.a58272fc2ef255219061.bundle.js:1)
at r.run (polyfills.a58272fc2ef255219061.bundle.js:1)
at polyfills.a58272fc2ef255219061.bundle.js:1
at t.invokeTask (polyfills.a58272fc2ef255219061.bundle.js:1)
at Object.onInvokeTask (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at Z (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at t.compileModuleAndAllComponentsAsync 
(vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at dynamic.module.3b05550d9afcedd58855.chunk.js:1
at t.invoke (polyfills.a58272fc2ef255219061.bundle.js:1)
at Object.onInvoke (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at t.invoke (polyfills.a58272fc2ef255219061.bundle.js:1)
at r.run (polyfills.a58272fc2ef255219061.bundle.js:1)
at polyfills.a58272fc2ef255219061.bundle.js:1
at t.invokeTask (polyfills.a58272fc2ef255219061.bundle.js:1)
at Object.onInvokeTask (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at c (polyfills.a58272fc2ef255219061.bundle.js:1)
at polyfills.a58272fc2ef255219061.bundle.js:1
at t.invokeTask (polyfills.a58272fc2ef255219061.bundle.js:1)
at Object.onInvokeTask (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at t.invokeTask (polyfills.a58272fc2ef255219061.bundle.js:1)
at r.runTask (polyfills.a58272fc2ef255219061.bundle.js:1)
at o (polyfills.a58272fc2ef255219061.bundle.js:1)
at <anonymous>`

通過在動態組件中應用注入器,我擺脫了上述錯誤:

export class DynamicComponent {
private injector: Injector;
private compiler: Compiler;
constructor(injector: Injector) {
    this.injector = ReflectiveInjector.resolveAndCreate(COMPILER_PROVIDERS,
        injector);
    this.compiler = this.injector.get(Compiler);
}
}

一旦上述錯誤消失,我現在得到以下錯誤:

vendor.fbd3ddffb0a9e35bbf55.bundle.js:1 ERROR Error: Uncaught (in promise): 
Error: No NgModule metadata found for 'l'.
Error: No NgModule metadata found for 'l'.
at t.FDXN.t.resolve (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at t.FDXN.t.getNgModuleMetadata (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at t.FDXN.t._loadModules (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at t.FDXN.t._compileModuleAndAllComponents (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at t.FDXN.t.compileModuleAndAllComponentsAsync (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at dynamic.module.c493eec4648091b2c9b3.chunk.js:1
at t.invoke (polyfills.a58272fc2ef255219061.bundle.js:1)
at Object.onInvoke (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at t.invoke (polyfills.a58272fc2ef255219061.bundle.js:1)
at r.run (polyfills.a58272fc2ef255219061.bundle.js:1)
at t.FDXN.t.resolve (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at t.FDXN.t.getNgModuleMetadata (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at t.FDXN.t._loadModules (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at t.FDXN.t._compileModuleAndAllComponents (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at t.FDXN.t.compileModuleAndAllComponentsAsync (dynamic.module.c493eec4648091b2c9b3.chunk.js:1)
at dynamic.module.c493eec4648091b2c9b3.chunk.js:1
at t.invoke (polyfills.a58272fc2ef255219061.bundle.js:1)
at Object.onInvoke (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at t.invoke (polyfills.a58272fc2ef255219061.bundle.js:1)
at r.run (polyfills.a58272fc2ef255219061.bundle.js:1)
at c (polyfills.a58272fc2ef255219061.bundle.js:1)
at polyfills.a58272fc2ef255219061.bundle.js:1
at t.invokeTask (polyfills.a58272fc2ef255219061.bundle.js:1)
at Object.onInvokeTask (vendor.fbd3ddffb0a9e35bbf55.bundle.js:1)
at t.invokeTask (polyfills.a58272fc2ef255219061.bundle.js:1)
at r.runTask (polyfills.a58272fc2ef255219061.bundle.js:1)
at o (polyfills.a58272fc2ef255219061.bundle.js:1)
at <anonymous>

我在互聯網上發現了很多與此問題相關的帖子,包括堆棧溢出,但是沒有一個適合我。

我的動態組件如下所示:

import { Component, Input, Output, ViewContainerRef, Compiler, ComponentFactory, ComponentFactoryResolver, ModuleWithComponentFactories, ComponentRef, ReflectiveInjector, SystemJsNgModuleLoader, OnInit, OnDestroy, ViewChild, Injector } from '@angular/core';
import { Http } from '@angular/http';
import { Observable, Subscription } from 'rxjs/Rx';
import { JitCompiler } from '@angular/compiler';
import { COMPILER_PROVIDERS } from '@angular/compiler';
import * as _ from 'lodash';
import { Page } from './interfaces/page';
import { PageService } from './services/page.service';
import { ActivePageService } from './services/active-page.service';

export class ModuleNode { modulePath: string; componentName: string; }
@Component({
selector: 'app-dynamic-viewer',
host: { 'class': 'template-wrapper dynamicviewer' },
templateUrl: './dynamic.component.html',
styleUrls: ['./dynamic.component.less'],
providers: [PageService, ActivePageService]
})
export class DynamicComponent implements OnInit, OnDestroy {
module: ModuleNode;
componentRef: ComponentRef<any>;
@ViewChild('pageContainer', { read: ViewContainerRef }) public pageHost;
public activePagesData: string[];
public pageData: Page[];
public currentPage: Page;
private injector: Injector;
private compiler: Compiler;

constructor(
    injector: Injector,
    private activePageService: activePageService,
    private pageService: pageService,
    private viewContainerRef: ViewContainerRef,
    private componentFactoryResolver: ComponentFactoryResolver,
    private systemJsNgModuleLoader: SystemJsNgModuleLoader
) {
    this.injector = ReflectiveInjector.resolveAndCreate(COMPILER_PROVIDERS, 
injector);
    this.compiler = this.injector.get(Compiler);
}

ngOnInit() {
    this.getActivePageData();
}

openWebApp(currentModule: any) {
    this.destoryComponent();
    this.systemJsNgModuleLoader.load(currentModule.modulePath)  
        .then((moduleFactory) => {
            this.compiler.compileModuleAndAllComponentsAsync<any>(moduleFactory.moduleType)
                .then((factory: ModuleWithComponentFactories<any>) => {
                    return factory.componentFactories.find(x => x.componentType.name === currentModule.componentName);
                })
                .then(componentFactory => {
                    const moduleRef = moduleFactory.create(this.pageHost.parentInjector);
                    this.componentRef = this.pageHost.createComponent(componentFactory, 0, moduleRef.injector);
                });
        });
}

destoryComponent() {
    if (this.componentRef) {
        this.componentRef.destroy();
    }
}

ngOnDestroy() {
    this.destoryComponent();
}

getPageData() {
    this.pageService.getPageData().subscribe(res => {
        for (const page of res) {
            page.active = (this.activePagesData.indexOf(page.name) !== -1)
        }
        this.pageData = res;

    });
}


getActivePageData() {
    this.activePageService.getActivePageData().subscribe(res => {
        this.activePagesData = res;
        this.getPageData();
    });
}

selectPage(page: Page) {
    if (page.active) {
        this.currentPage = page;
        if (this.componentRef) {
            this.componentRef.destroy();
        }
        this.module = new ModuleNode();
        this.module.modulePath = this.currentPage.modulePath;
        this.module.componentName = this.currentPage.componentName;
        this.openWebApp(this.module);
    }
}
}

應用環境:

@angular/cli: 1.3.0-beta.1
node: 6.9.4
os: win32 x64
@angular version: 4.3.6

有什么解決方法嗎? 任何輸入將不勝感激。

我也遇到了同樣的問題。 這就是我做到的方式。 假設, UserComponent needs to be loaded dynamically從您的登錄頁面通過AOT編譯UserComponent needs to be loaded dynamically

user.module.ts

@NgModule({
  ...
  entryComponents: [UserComponent]
})
export class UserModule {
  static entry = UserComponent
}

您的基本目標網頁可以是:

dynamic.component.htlm

<div>
    <ng-template #pageContainer></ng-template>
</div>    
<div *ngFor="let page of pageData">
    <div (click)="selectPage(page)">
        <div>{{page.title}}</div>
    </div>
</div>

當您從登錄頁面選擇頁面(即嘗試動態加載組件)時,請提供相應模塊的絕對路徑。 因此,用戶頁面的currentPage.modulePath的值可能類似於app/modules/pages/user/user.module#UserModule 最后,您可以像這樣加載您的輸入組件:

openWebApp(path: string) {
        this.systemJsNgModuleLoader.load(path)
            .then((moduleFactory: NgModuleFactory<any>) => {
                const entryComponent = (<any>moduleFactory.moduleType).entry;
                const moduleRef = moduleFactory.create(this.injector);    
                const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
                this.componentRef = this.pageHost.createComponent(compFactory);
            });
    }

因此,您的動態組件如下所示:

dynamic.component.ts

import { Component, Input, Output,   NgModuleFactory, ViewContainerRef, Compiler, ComponentFactory, ComponentFactoryResolver, ModuleWithComponentFactories, ComponentRef, ReflectiveInjector, SystemJsNgModuleLoader, OnInit, OnDestroy, ViewChild, Injector } from '@angular/core';
import { Http } from '@angular/http';
import { Observable, Subscription } from 'rxjs/Rx';    
import { COMPILER_PROVIDERS } from '@angular/compiler';
import * as _ from 'lodash';    
import { Page } from './interfaces/page';
import { PageService } from './services/page.service';
import { ActivePageService } from './services/active-page.service';

@Component({
    selector: 'app-dynamic-viewer',
    host: { 'class': 'template-wrapper dynamicviewer' },
    templateUrl: './dynamic.component.html',
    styleUrls: ['./dynamic.component.less'],
    providers: [PageService, ActivePageService]
})
export class DynamicComponent implements OnInit, OnDestroy {
    componentRef: ComponentRef<any>;
    @ViewChild('pageContainer', { read: ViewContainerRef }) public pageHost;
    public activePagesData: string[];
    public pageData: Page[];
    public currentPage: Page;
    private injector: Injector;
    private compiler: Compiler;

    constructor(
        injector: Injector,
        private activePageService: ActivePageService,
        private pageService: PageService,
        private viewContainerRef: ViewContainerRef,
        private componentFactoryResolver: ComponentFactoryResolver,
        private systemJsNgModuleLoader: SystemJsNgModuleLoader
    ) {
        this.injector = ReflectiveInjector.resolveAndCreate(COMPILER_PROVIDERS, injector);
        this.compiler = this.injector.get(Compiler);
    }

    ngOnInit() {
        this.getActivePageData();
    }

    selectPage(page: Page) {
        if (page.active) {
            this.currentPage = page;
            if (this.componentRef) {
                this.componentRef.destroy();
            }    
            this.openWebApp(this.currentPage.modulePath);
        }
    }

    openWebApp(path: string) {
        this.destoryComponent();
        this.systemJsNgModuleLoader.load(path)
            .then((moduleFactory: NgModuleFactory<any>) => {
                const entryComponent = (<any>moduleFactory.moduleType).entry;
                const moduleRef = moduleFactory.create(this.injector);    
                const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
                this.componentRef = this.pageHost.createComponent(compFactory);
            });
    }

    destoryComponent() {
        if (this.componentRef) {
            this.componentRef.destroy();
        }
    }

    ngOnDestroy() {
        this.destoryComponent();
    }

    getPageData() {
        this.pageService.getPageData().subscribe(res => {
            for (const page of res) {
                page.active = (this.activePagesData.indexOf(page.name) !== -1)
            }    
            this.pageData = res;
        });
    }


    getActivePageData() {
        this.activePageService.getActivePageData().subscribe(res => {
            this.activePagesData = res;
            this.getPageData();
        });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM