Skip to content

Commit 5aeba2b

Browse files
Update to Angular 4 (but leave directory name as Angular2Spa until we merge)
1 parent d016950 commit 5aeba2b

8 files changed

Lines changed: 93 additions & 67 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { NgModule } from '@angular/core';
2+
import { BrowserModule } from '@angular/platform-browser';
3+
import { FormsModule } from '@angular/forms';
4+
import { HttpModule } from '@angular/http';
5+
import { sharedConfig } from './app.module';
6+
7+
@NgModule({
8+
bootstrap: sharedConfig.bootstrap,
9+
declarations: sharedConfig.declarations,
10+
imports: [
11+
BrowserModule,
12+
FormsModule,
13+
HttpModule,
14+
...sharedConfig.imports
15+
],
16+
providers: [
17+
{ provide: 'ORIGIN_URL', useValue: location.origin }
18+
]
19+
})
20+
export class AppModule {
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { NgModule } from '@angular/core';
2+
import { ServerModule } from '@angular/platform-server';
3+
import { sharedConfig } from './app.module';
4+
5+
@NgModule({
6+
bootstrap: sharedConfig.bootstrap,
7+
declarations: sharedConfig.declarations,
8+
imports: [
9+
ServerModule,
10+
...sharedConfig.imports
11+
]
12+
})
13+
export class AppModule {
14+
}
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { NgModule } from '@angular/core';
22
import { RouterModule } from '@angular/router';
3-
import { UniversalModule } from 'angular2-universal';
3+
44
import { AppComponent } from './components/app/app.component'
55
import { NavMenuComponent } from './components/navmenu/navmenu.component';
66
import { HomeComponent } from './components/home/home.component';
77
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
88
import { CounterComponent } from './components/counter/counter.component';
99

10-
@NgModule({
10+
export const sharedConfig: NgModule = {
1111
bootstrap: [ AppComponent ],
1212
declarations: [
1313
AppComponent,
@@ -17,7 +17,6 @@ import { CounterComponent } from './components/counter/counter.component';
1717
HomeComponent
1818
],
1919
imports: [
20-
UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
2120
RouterModule.forRoot([
2221
{ path: '', redirectTo: 'home', pathMatch: 'full' },
2322
{ path: 'home', component: HomeComponent },
@@ -26,6 +25,4 @@ import { CounterComponent } from './components/counter/counter.component';
2625
{ path: '**', redirectTo: 'home' }
2726
])
2827
]
29-
})
30-
export class AppModule {
31-
}
28+
};

‎templates/Angular2Spa/ClientApp/app/components/fetchdata/fetchdata.component.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component } from '@angular/core';
1+
import { Component, Inject } from '@angular/core';
22
import { Http } from '@angular/http';
33

44
@Component({
@@ -8,8 +8,8 @@ import { Http } from '@angular/http';
88
export class FetchDataComponent {
99
public forecasts: WeatherForecast[];
1010

11-
constructor(http: Http) {
12-
http.get('/api/SampleData/WeatherForecasts').subscribe(result => {
11+
constructor(http: Http, @Inject('ORIGIN_URL') originUrl: string) {
12+
http.get(originUrl + '/api/SampleData/WeatherForecasts').subscribe(result => {
1313
this.forecasts = result.json() as WeatherForecast[];
1414
});
1515
}
Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,22 @@
1-
import 'angular2-universal-polyfills/browser';
1+
import 'reflect-metadata';
2+
import 'zone.js';
23
import { enableProdMode } from '@angular/core';
3-
import { platformUniversalDynamic } from 'angular2-universal';
4-
import { AppModule } from './app/app.module';
5-
import 'bootstrap';
6-
const rootElemTagName = 'app'; // Update this if you change your root component selector
4+
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
5+
import { AppModule } from './app/app.module.client';
76

8-
// Enable either Hot Module Reloading or production mode
97
if (module['hot']) {
108
module['hot'].accept();
119
module['hot'].dispose(() => {
1210
// Before restarting the app, we create a new root element and dispose the old one
13-
const oldRootElem = document.querySelector(rootElemTagName);
14-
const newRootElem = document.createElement(rootElemTagName);
11+
const oldRootElem = document.querySelector('app');
12+
const newRootElem = document.createElement('app');
1513
oldRootElem.parentNode.insertBefore(newRootElem, oldRootElem);
16-
platform.destroy();
14+
modulePromise.then(appModule => appModule.destroy());
1715
});
1816
} else {
1917
enableProdMode();
2018
}
2119

22-
// Boot the application, either now or when the DOM content is loaded
23-
const platform = platformUniversalDynamic();
24-
const bootApplication = () => { platform.bootstrapModule(AppModule); };
25-
if (document.readyState === 'complete') {
26-
bootApplication();
27-
} else {
28-
document.addEventListener('DOMContentLoaded', bootApplication);
29-
}
20+
// Note: @ng-tools/webpack looks for the following expression when performing production
21+
// builds. Don't change how this line looks, otherwise you may break tree-shaking.
22+
const modulePromise = platformBrowserDynamic().bootstrapModule(AppModule);
Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,36 @@
1-
import 'angular2-universal-polyfills';
2-
import 'angular2-universal-patch';
1+
import 'core-js/shim';
32
import 'zone.js';
3+
import 'rxjs/add/operator/first';
4+
import { enableProdMode, ApplicationRef, NgZone, ValueProvider } from '@angular/core';
5+
import { platformDynamicServer, PlatformState, INITIAL_CONFIG } from '@angular/platform-server';
46
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
5-
import { enableProdMode } from '@angular/core';
6-
import { platformNodeDynamic } from 'angular2-universal';
7-
import { AppModule } from './app/app.module';
7+
import { AppModule } from './app/app.module.server';
88

99
enableProdMode();
10-
const platform = platformNodeDynamic();
1110

1211
export default createServerRenderer(params => {
13-
return new Promise<RenderResult>((resolve, reject) => {
14-
const requestZone = Zone.current.fork({
15-
name: 'angular-universal request',
16-
properties: {
17-
baseUrl: '/',
18-
requestUrl: params.url,
19-
originUrl: params.origin,
20-
preboot: false,
21-
document: '<app></app>'
22-
},
23-
onHandleError: (parentZone, currentZone, targetZone, error) => {
24-
// If any error occurs while rendering the module, reject the whole operation
25-
reject(error);
26-
return true;
27-
}
28-
});
12+
const providers = [
13+
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
14+
{ provide: 'ORIGIN_URL', useValue: params.origin }
15+
];
16+
17+
return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
18+
const appRef = moduleRef.injector.get(ApplicationRef);
19+
const state = moduleRef.injector.get(PlatformState);
20+
const zone = moduleRef.injector.get(NgZone);
2921

30-
return requestZone.run<Promise<string>>(() => platform.serializeModule(AppModule)).then(html => {
31-
resolve({ html: html });
32-
}, reject);
22+
return new Promise<RenderResult>((resolve, reject) => {
23+
zone.onError.subscribe(errorInfo => reject(errorInfo));
24+
appRef.isStable.first(isStable => isStable).subscribe(() => {
25+
// Because 'onStable' fires before 'onError', we have to delay slightly before
26+
// completing the request in case there's an error to report
27+
setImmediate(() => {
28+
resolve({
29+
html: state.renderToString()
30+
});
31+
moduleRef.destroy();
32+
});
33+
});
34+
});
3335
});
3436
});

‎templates/Angular2Spa/package.json‎

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,19 @@
55
"test": "karma start ClientApp/test/karma.conf.js"
66
},
77
"dependencies": {
8-
"@angular/common": "^2.4.5",
9-
"@angular/compiler": "^2.4.5",
10-
"@angular/core": "^2.4.5",
11-
"@angular/forms": "^2.4.5",
12-
"@angular/http": "^2.4.5",
13-
"@angular/platform-browser": "^2.4.5",
14-
"@angular/platform-browser-dynamic": "^2.4.5",
15-
"@angular/platform-server": "^2.4.5",
16-
"@angular/router": "^3.4.5",
8+
"@angular/animations": "^4.0.0",
9+
"@angular/common": "^4.0.0",
10+
"@angular/compiler": "^4.0.0",
11+
"@angular/core": "^4.0.0",
12+
"@angular/forms": "^4.0.0",
13+
"@angular/http": "^4.0.0",
14+
"@angular/platform-browser": "^4.0.0",
15+
"@angular/platform-browser-dynamic": "^4.0.0",
16+
"@angular/platform-server": "^4.0.0",
17+
"@angular/router": "^4.0.0",
1718
"@types/node": "^6.0.42",
1819
"angular2-platform-node": "~2.0.11",
1920
"angular2-template-loader": "^0.6.2",
20-
"angular2-universal": "^2.1.0-rc.1",
21-
"angular2-universal-patch": "^0.2.1",
22-
"angular2-universal-polyfills": "^2.1.0-rc.1",
2321
"aspnet-prerendering": "^2.0.0",
2422
"aspnet-webpack": "^1.0.17",
2523
"awesome-typescript-loader": "^3.0.0",
@@ -37,6 +35,7 @@
3735
"json-loader": "^0.5.4",
3836
"preboot": "^4.5.2",
3937
"raw-loader": "^0.5.1",
38+
"reflect-metadata": "^0.1.10",
4039
"rxjs": "^5.0.1",
4140
"style-loader": "^0.13.1",
4241
"to-string-loader": "^1.1.5",
@@ -45,7 +44,7 @@
4544
"webpack": "^2.2.0",
4645
"webpack-hot-middleware": "^2.12.2",
4746
"webpack-merge": "^0.14.1",
48-
"zone.js": "^0.7.6"
47+
"zone.js": "^0.8.4"
4948
},
5049
"devDependencies": {
5150
"@types/chai": "^3.4.34",

‎templates/Angular2Spa/webpack.config.vendor.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,15 @@ module.exports = (env) => {
1616
},
1717
entry: {
1818
vendor: [
19+
'@angular/animations',
1920
'@angular/common',
2021
'@angular/compiler',
2122
'@angular/core',
23+
'@angular/forms',
2224
'@angular/http',
2325
'@angular/platform-browser',
2426
'@angular/platform-browser-dynamic',
2527
'@angular/router',
26-
'@angular/platform-server',
27-
'angular2-universal',
28-
'angular2-universal-polyfills',
2928
'bootstrap',
3029
'bootstrap/dist/css/bootstrap.css',
3130
'es6-shim',
@@ -43,6 +42,7 @@ module.exports = (env) => {
4342
plugins: [
4443
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)
4544
new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/11580
45+
new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/14898
4646
new webpack.IgnorePlugin(/^vertx$/) // Workaround for https://github.com/stefanpenner/es6-promise/issues/100
4747
]
4848
};

0 commit comments

Comments
 (0)