From 505ebcf1e6a48f1a08c8e316eb95011dda043fe4 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 22 Nov 2017 15:17:34 +0000 Subject: [PATCH] Update to newer Angular SSR APIs to support AoT-enabled builds --- .../Angular-CSharp.csproj.in | 1 + .../ClientApp/npm-shrinkwrap.json | 5 ++ .../Angular-CSharp/ClientApp/package.json | 3 +- .../ClientApp/src/app/app.server.module.ts | 3 +- .../ClientApp/src/main.server.ts | 51 ++++++++----------- 5 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/Angular-CSharp.csproj.in b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/Angular-CSharp.csproj.in index ac58fc8819..d5daa84a8f 100644 --- a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/Angular-CSharp.csproj.in +++ b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/Angular-CSharp.csproj.in @@ -56,6 +56,7 @@ + %(DistFiles.Identity) PreserveNewest diff --git a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/npm-shrinkwrap.json b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/npm-shrinkwrap.json index 09656a7474..5c2fa34088 100644 --- a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/npm-shrinkwrap.json +++ b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/npm-shrinkwrap.json @@ -78,6 +78,11 @@ } } }, + "@nguniversal/module-map-ngfactory-loader": { + "version": "5.0.0-beta.5", + "from": "@nguniversal/module-map-ngfactory-loader@latest", + "resolved": "https://registry.npmjs.org/@nguniversal/module-map-ngfactory-loader/-/module-map-ngfactory-loader-5.0.0-beta.5.tgz" + }, "@schematics/angular": { "version": "0.1.3", "dev": true diff --git a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/package.json b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/package.json index 99185e471e..624231a538 100644 --- a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/package.json +++ b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/package.json @@ -6,7 +6,7 @@ "ng": "ng", "start": "ng serve --deploy-url=/dist/ --output-hashing=media --extract-css", "build": "ng build --deploy-url=/dist/ --output-hashing=media --extract-css", - "build:ssr": "ng build --deploy-url=/dist/ --output-hashing=media --extract-css --bundle-dependencies=all --app=ssr", + "build:ssr": "ng build --deploy-url=/dist/ --output-hashing=media --extract-css --app=ssr", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" @@ -23,6 +23,7 @@ "@angular/platform-browser-dynamic": "^5.0.0", "@angular/platform-server": "^5.0.0", "@angular/router": "^5.0.0", + "@nguniversal/module-map-ngfactory-loader": "^5.0.0-beta.5", "aspnet-prerendering": "^3.0.1", "bootstrap": "^3.3.7", "core-js": "^2.4.1", diff --git a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/app.server.module.ts b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/app.server.module.ts index 316380b634..cfb0e021a9 100644 --- a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/app.server.module.ts +++ b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/app.server.module.ts @@ -1,10 +1,11 @@ import { NgModule } from '@angular/core'; import { ServerModule } from '@angular/platform-server'; +import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader'; import { AppComponent } from './app.component'; import { AppModule } from './app.module'; @NgModule({ - imports: [AppModule, ServerModule], + imports: [AppModule, ServerModule, ModuleMapLoaderModule], bootstrap: [AppComponent] }) export class AppServerModule { } diff --git a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/main.server.ts b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/main.server.ts index 84a37c1b18..4b9070961b 100644 --- a/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/main.server.ts +++ b/src/Microsoft.DotNet.Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/main.server.ts @@ -1,38 +1,29 @@ +import 'zone.js/dist/zone-node'; import 'reflect-metadata'; -import 'zone.js'; -import 'rxjs/add/operator/first'; +import { renderModule, renderModuleFactory } from '@angular/platform-server'; import { APP_BASE_HREF } from '@angular/common'; -import { enableProdMode, ApplicationRef, NgModule, NgZone, ValueProvider } from '@angular/core'; -import { platformDynamicServer, PlatformState, INITIAL_CONFIG } from '@angular/platform-server'; -import { AppServerModule } from './app/app.server.module'; -import { createServerRenderer, RenderResult } from 'aspnet-prerendering'; +import { enableProdMode } from '@angular/core'; +import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; +import { createServerRenderer } from 'aspnet-prerendering'; +export { AppServerModule } from './app/app.server.module'; +const { AppServerModule, AppServerModuleNgFactory, LAZY_MODULE_MAP } = (module as any).exports; enableProdMode(); export default createServerRenderer(params => { - const providers = [ - { provide: INITIAL_CONFIG, useValue: { document: params.data.originalHtml, url: params.url } }, - { provide: APP_BASE_HREF, useValue: params.baseUrl }, - { provide: 'BASE_URL', useValue: params.origin + params.baseUrl }, - ]; + const options = { + document: params.data.originalHtml, + url: params.url, + extraProviders: [ + provideModuleMap(LAZY_MODULE_MAP), + { provide: APP_BASE_HREF, useValue: params.baseUrl }, + { provide: 'BASE_URL', useValue: params.origin + params.baseUrl } + ] + }; - return platformDynamicServer(providers).bootstrapModule(AppServerModule).then(moduleRef => { - const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef); - const state = moduleRef.injector.get(PlatformState); - const zone: NgZone = moduleRef.injector.get(NgZone); - - return new Promise((resolve, reject) => { - zone.onError.subscribe((errorInfo: any) => reject(errorInfo)); - appRef.isStable.first(isStable => isStable).subscribe(() => { - // Because 'onStable' fires before 'onError', we have to delay slightly before - // completing the request in case there's an error to report - setImmediate(() => { - resolve({ - html: state.renderToString() - }); - moduleRef.destroy(); - }); - }); - }); - }); + const renderPromise = AppServerModuleNgFactory + ? /* AoT */ renderModuleFactory(AppServerModuleNgFactory, options) + : /* dev */ renderModule(AppServerModule, options); + + return renderPromise.then(html => ({ html })); });