Search code examples
angular-cliangular5hybridaot

How can I do a Angular 5 --aot build using ngc?


I am getting very confused, in the documents I read about using ngc to generate the factories in an "aot" folder and then referencing it in main.js like:

import { AppModuleNgFactory } from './app/app.module.ngfactory';

and in angular 4 it worked but in angular 5 (using 5.2.0) it doesn't generate the "aot" folder at all. I also read in the angular 5.0.0 blog that ng-build doesn't generate an aot folder due to the integration with the tsc compiler. But the ng build --aot command seem to be very dependant on urls and where you deploy it due to the webpack magic going on. The old ngc solution was not and I could rollup it like it needed.

Questions

  1. Is ngc dead for "aot" builds now?
  2. If not, how can I do aot builds with ngc?
  3. Should I always use platformBrowserDynamic instead of platformBrowser now?
  4. What more am I missing to get this to run? I am getting very frustrated after days of nothing. Please help! :)

My file structure looks like:

  • some/path/
    • index.html
    • src/
      • main.ts
      • tsconfig.json
      • modules/
        • app.module.ts

and I cannot know what base url will be used.

my tsconfig looks like this:

{
    "compileOnSave": false,
    "compilerOptions": {
        "module": "es2015",
        "outDir": "../out-ngc",
        "sourceMap": true,
        "declaration": false,
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "target": "es5",
        "typeRoots": [
            "../node_modules/@types",
            "./typings"
        ],
        "lib": [
            "es2017",
            "dom"
        ]
    },
    "include": [
        "./modules/**/*.module.ts",
        "./main.ts"
    ],
    "exclude": [
        "test.ts",
        "**/*.spec.ts",
        "_NOT_USED_"
    ],
    "angularCompilerOptions": {
        "entryModule": "./modules/app.module#AppModule",
        "genDir": "aot"
    }

}

My main.ts looks like:

import { NgModule, StaticProvider } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { downgradeModule, downgradeComponent, downgradeInjectable } from "@angular/upgrade/static";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

import { enableProdMode } from "@angular/core";
import { AppModule } from "./modules/app.module";

import "zone.js/dist/zone";
import { environment } from "./environments/environment.prod";

import { FormsModule } from "@angular/forms";
import { BsDatepickerModule, ModalModule, PopoverModule } from "ngx-bootstrap";
import { NgSelectModule } from "@ng-select/ng-select";

import * as d3 from "d3";
import { BsDatepickerConfig } from 'ngx-bootstrap/datepicker/bs-datepicker.config';
if (environment.production) {
    enableProdMode();
}

declare var angular: any;
const bootstrapFn = (extraProviders: StaticProvider[]) => {
    let module = platformBrowserDynamic(extraProviders).bootstrapModule(AppModule);
    return module;
};
const downgradedModule = downgradeModule(bootstrapFn);

angular.module(AppModule.name, [
    "oneClientApp",
    downgradedModule, BrowserModule, downgradeComponent, downgradeInjectable, FormsModule, BsDatepickerConfig, ModalModule, PopoverModule, NgSelectModule
]);

angular.bootstrap(document.body, [AppModule.name]);

My app.module.ts looks like:

import { NgModule, StaticProvider } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { downgradeModule, downgradeComponent, downgradeInjectable } from "@angular/upgrade/static";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

import { FormsModule } from "@angular/forms";
import { BsDatepickerModule, ModalModule, PopoverModule } from "ngx-bootstrap";
import { NgSelectModule } from "@ng-select/ng-select";

import { BroadcastService } from "./app_components/shared/services/broadcast.service";

import { Foo } from "./app_components/foo/foo.component";

const moduleName = "myAppModule";

@NgModule({
    declarations: [
        Foo
    ],
    entryComponents: [
        Foo
    ],
    imports: [
        BrowserModule,
        FormsModule,
        NgSelectModule,
        ModalModule.forRoot(),
        PopoverModule.forRoot(),
        BsDatepickerModule.forRoot()
    ],
    providers: [
        BroadcastService,
    ],
    bootstrap: [
    ]
})
export class AppModule {
    name: string = moduleName;
    constructor() { }
    ngDoBootstrap() {

    }
}

declare var angular: ng.IAngularStatic;
angular.module(moduleName).directive("foo", downgradeComponent({ component: Foo }));

angular.module(moduleName).factory("broadcastService", downgradeInjectable(BroadcastService) as any);

Solution

  • I just found this repo: angular 5 aot example repo

    Basically it solves it and my answers are:

    1. No, ngc works fine, BUT it doesn't generate an aot folder and you will have a red squiggly since you reference a factory in a file that doesn't exist yet.
    2. look at the repo.
    3. platformBrowser for aot builds