New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can compileModuleSync compile incrementally #28064

Closed
10229428 opened this Issue Jan 11, 2019 · 1 comment

Comments

Projects
None yet
3 participants
@10229428
Copy link

10229428 commented Jan 11, 2019

馃殌 feature request

Relevant Package

This feature request is for @angular/core
export declare class Compiler {
    /**
     * Compiles the given NgModule and all of its components. All templates of the components listed
     * in `entryComponents` have to be inlined.
     */
    compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T>;
    /**
     * Compiles the given NgModule and all of its components
     */
    compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>>;
    /**
     * Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.
     */
    compileModuleAndAllComponentsSync<T>(moduleType: Type<T>): ModuleWithComponentFactories<T>;
    /**
     * Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.
     */
    compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>): Promise<ModuleWithComponentFactories<T>>;
    /**
     * Clears all caches.
     */
    clearCache(): void;
    /**
     * Clears the cache for the given component/ngModule.
     */
    clearCacheFor(type: Type<any>): void;
}

Description

It seem impossible to use Compiler.compileModuleSync to compile dynamic module incrementally. So when there are many components in the dynamic module , It will cost much time!

Describe the solution you'd like

I hope I can compile the dynamic module incrementally. Or, I can remove or add component into the dynamic module, not compile the whole dynamic module every time.
My code:

import {Compiler, Component, Input, NgModule, NgModuleFactory, OnChanges, OnInit, SimpleChanges} from "@angular/core";
import {HTTP_INTERCEPTORS, HttpClient} from "@angular/common/http";
import {RouterModule, Routes} from '@angular/router';
import {TranslateModule, TranslateService} from '@ngx-translate/core';

@Component({
    selector: 'uid-dynamic',
    template: `
        <ng-container *ngComponentOutlet="dynamicComponent; ngModuleFactory: dynamicModule;">
        </ng-container>
    `
})
export class DynamicComponent implements OnInit, OnChanges {

    dynamicComponent: any;
    dynamicModule: NgModuleFactory<any>;
    @Input()
    dynamicStr: string;
    @Input()
    component: string;

    constructor(private compiler: Compiler) {
    }

    ngOnChanges(changes: SimpleChanges) {
        if (changes['dynamicStr'] && !changes['dynamicStr'].isFirstChange()) {
            this._createClasses(this.dynamicStr);
        }
    }

    ngOnInit() {
        this._createClasses(this.dynamicStr);
    }

    private _createClasses(dynamicStr) {
        let tempComponents = [];
        [...there are componen code...].forEach((item) => {
            tempComponents.push(this.createNewComponent(item.code))
        });

        let dynamicComponent = this.createNewComponent(dynamicStr);
        let dynamicModule = null;
        if (dynamicComponent) {
            dynamicModule = this.compiler.compileModuleSync(this.createComponentModule(tempComponents));
        }
        if (dynamicComponent && dynamicModule) {
            this.dynamicComponent = dynamicComponent;
            this.dynamicModule = dynamicModule;
        }
    }
    protected createComponentModule(componentTypes: any[]) {
        @NgModule({
            imports: [
                AgentModule, PerfectScrollbarModule,TranslateModule.forRoot(), LayoutModules, 
            ],
            declarations: componentTypes,
            providers: [],
            entryComponents: componentTypes
        })
        class RuntimeComponentModule {
            constructor() {  }
        }
        // a module for just this Type
        return RuntimeComponentModule;
    }
    protected createNewComponent(dynamicStr: string) {
        try {
            return eval(dynamicStr);
        } catch (e) {
            console.error('eval dynamic component source code failed: ' + e);
            return null;
        }
    }
}

@alxhub

This comment has been minimized.

Copy link
Contributor

alxhub commented Jan 15, 2019

Sadly, the design of the Compiler (and NgModules in general) make this unlikely to be easily implemented. Without compiling all the components in a module, it's impossible to know which parts of the module's declarations need to be compiled. Ivy may have a better story here, stay tuned.

(I'm closing this as under Ivy, the specific Compiler API in question is a no-op, components are compiled when declared in JIT).

@alxhub alxhub closed this Jan 15, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment