diff --git a/packages/@ngtools/webpack/src/loader.ts b/packages/@ngtools/webpack/src/loader.ts index 97bd6b1feda4..5dd0c0f7ab4d 100644 --- a/packages/@ngtools/webpack/src/loader.ts +++ b/packages/@ngtools/webpack/src/loader.ts @@ -4,9 +4,25 @@ import {AotPlugin} from './plugin'; import {TypeScriptFileRefactor} from './refactor'; import {LoaderContext, ModuleReason} from './webpack'; +interface Platform { + name: string; + importLocation: string; +} + const loaderUtils = require('loader-utils'); const NormalModule = require('webpack/lib/NormalModule'); +// This is a map of changes which need to be made +const changeMap: {[key: string]: Platform} = { + platformBrowserDynamic: { + name: 'platformBrowser', + importLocation: '@angular/platform-browser' + }, + platformDynamicServer: { + name: 'platformServer', + importLocation: '@angular/platform-server' + } +}; function _getContentOfKeyLiteral(_source: ts.SourceFile, node: ts.Node): string { if (!node) { @@ -205,9 +221,10 @@ function _replaceBootstrap(plugin: AotPlugin, refactor: TypeScriptFileRefactor) = refactor.findAstNodes(access, ts.SyntaxKind.CallExpression, true) as ts.CallExpression[]; return previous.concat(expressions); }, []) + .filter((call: ts.CallExpression) => call.expression.kind == ts.SyntaxKind.Identifier) .filter((call: ts.CallExpression) => { - return call.expression.kind == ts.SyntaxKind.Identifier - && (call.expression as ts.Identifier).text == 'platformBrowserDynamic'; + // Find if the expression matches one of the replacement targets + return !!changeMap[(call.expression as ts.Identifier).text]; }); if (calls.length == 0) { @@ -222,7 +239,15 @@ function _replaceBootstrap(plugin: AotPlugin, refactor: TypeScriptFileRefactor) refactor.replaceNode(call.arguments[0], entryModule.className + 'NgFactory'); }); - calls.forEach(call => refactor.replaceNode(call.expression, 'platformBrowser')); + calls.forEach(call => { + const platform = changeMap[(call.expression as ts.Identifier).text]; + + // Replace with mapped replacement + refactor.replaceNode(call.expression, platform.name); + + // Add the appropriate import + refactor.insertImport(platform.name, platform.importLocation); + }); bootstraps .forEach((bs: ts.PropertyAccessExpression) => { @@ -230,7 +255,6 @@ function _replaceBootstrap(plugin: AotPlugin, refactor: TypeScriptFileRefactor) refactor.replaceNode(bs.name, 'bootstrapModuleFactory'); }); - refactor.insertImport('platformBrowser', '@angular/platform-browser'); refactor.insertImport(entryModule.className + 'NgFactory', ngFactoryPath); } diff --git a/tests/e2e/assets/webpack/test-server-app/app/app.component.html b/tests/e2e/assets/webpack/test-server-app/app/app.component.html new file mode 100644 index 000000000000..5a532db9308f --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/app.component.html @@ -0,0 +1,5 @@ +
diff --git a/tests/e2e/assets/webpack/test-server-app/app/app.component.scss b/tests/e2e/assets/webpack/test-server-app/app/app.component.scss new file mode 100644 index 000000000000..5cde7b922336 --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/app.component.scss @@ -0,0 +1,3 @@ +:host { + background-color: blue; +} diff --git a/tests/e2e/assets/webpack/test-server-app/app/app.component.ts b/tests/e2e/assets/webpack/test-server-app/app/app.component.ts new file mode 100644 index 000000000000..82a4059565d3 --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component, ViewEncapsulation} from '@angular/core'; +import {MyInjectable} from './injectable'; + + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class AppComponent { + constructor(public inj: MyInjectable) { + console.log(inj); + } +} diff --git a/tests/e2e/assets/webpack/test-server-app/app/app.module.ts b/tests/e2e/assets/webpack/test-server-app/app/app.module.ts new file mode 100644 index 000000000000..6f8407fdfd29 --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/app.module.ts @@ -0,0 +1,27 @@ +import { NgModule, Component } from '@angular/core'; +import { ServerModule } from '@angular/platform-server'; +import { RouterModule } from '@angular/router'; +import { AppComponent } from './app.component'; + +@Component({ + selector: 'home-view', + template: 'home!' +}) +export class HomeView {} + + +@NgModule({ + declarations: [ + AppComponent, + HomeView + ], + imports: [ + ServerModule, + RouterModule.forRoot([ + {path: 'lazy', loadChildren: './lazy.module#LazyModule'}, + {path: '', component: HomeView} + ]) + ], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/tests/e2e/assets/webpack/test-server-app/app/feature/feature.module.ts b/tests/e2e/assets/webpack/test-server-app/app/feature/feature.module.ts new file mode 100644 index 000000000000..f464ca028b05 --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/feature/feature.module.ts @@ -0,0 +1,20 @@ +import {NgModule, Component} from '@angular/core'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'feature-component', + template: 'foo.html' +}) +export class FeatureComponent {} + +@NgModule({ + declarations: [ + FeatureComponent + ], + imports: [ + RouterModule.forChild([ + { path: '', component: FeatureComponent} + ]) + ] +}) +export class FeatureModule {} diff --git a/tests/e2e/assets/webpack/test-server-app/app/feature/lazy-feature.module.ts b/tests/e2e/assets/webpack/test-server-app/app/feature/lazy-feature.module.ts new file mode 100644 index 000000000000..8fafca158b24 --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/feature/lazy-feature.module.ts @@ -0,0 +1,23 @@ +import {NgModule, Component} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {HttpModule, Http} from '@angular/http'; + +@Component({ + selector: 'lazy-feature-comp', + template: 'lazy feature!' +}) +export class LazyFeatureComponent {} + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path: '', component: LazyFeatureComponent, pathMatch: 'full'}, + {path: 'feature', loadChildren: './feature.module#FeatureModule'} + ]), + HttpModule + ], + declarations: [LazyFeatureComponent] +}) +export class LazyFeatureModule { + constructor(http: Http) {} +} diff --git a/tests/e2e/assets/webpack/test-server-app/app/injectable.ts b/tests/e2e/assets/webpack/test-server-app/app/injectable.ts new file mode 100644 index 000000000000..04d8486586c4 --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/injectable.ts @@ -0,0 +1,8 @@ +import {Injectable, Inject, ViewContainerRef} from '@angular/core'; +import {DOCUMENT} from '@angular/platform-browser'; + + +@Injectable() +export class MyInjectable { + constructor(public viewContainer: ViewContainerRef, @Inject(DOCUMENT) public doc) {} +} diff --git a/tests/e2e/assets/webpack/test-server-app/app/lazy.module.ts b/tests/e2e/assets/webpack/test-server-app/app/lazy.module.ts new file mode 100644 index 000000000000..96da4de7515b --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/lazy.module.ts @@ -0,0 +1,26 @@ +import {NgModule, Component} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {HttpModule, Http} from '@angular/http'; + +@Component({ + selector: 'lazy-comp', + template: 'lazy!' +}) +export class LazyComponent {} + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path: '', component: LazyComponent, pathMatch: 'full'}, + {path: 'feature', loadChildren: './feature/feature.module#FeatureModule'}, + {path: 'lazy-feature', loadChildren: './feature/lazy-feature.module#LazyFeatureModule'} + ]), + HttpModule + ], + declarations: [LazyComponent] +}) +export class LazyModule { + constructor(http: Http) {} +} + +export class SecondModule {} diff --git a/tests/e2e/assets/webpack/test-server-app/app/main.ts b/tests/e2e/assets/webpack/test-server-app/app/main.ts new file mode 100644 index 000000000000..9aae9848fbcc --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/app/main.ts @@ -0,0 +1,5 @@ +import 'core-js/es7/reflect'; +import {platformDynamicServer} from '@angular/platform-server'; +import {AppModule} from './app.module'; + +platformDynamicServer().bootstrapModule(AppModule); diff --git a/tests/e2e/assets/webpack/test-server-app/index.html b/tests/e2e/assets/webpack/test-server-app/index.html new file mode 100644 index 000000000000..89fb0893c35d --- /dev/null +++ b/tests/e2e/assets/webpack/test-server-app/index.html @@ -0,0 +1,12 @@ + + + +