mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-22 17:47:53 +00:00
Update to Angular 4 (but leave directory name as Angular2Spa until finished)
This commit is contained in:
21
templates/Angular2Spa/ClientApp/app/app.module.client.ts
Normal file
21
templates/Angular2Spa/ClientApp/app/app.module.client.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { sharedConfig } from './app.module.shared';
|
||||
|
||||
@NgModule({
|
||||
bootstrap: sharedConfig.bootstrap,
|
||||
declarations: sharedConfig.declarations,
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule,
|
||||
...sharedConfig.imports
|
||||
],
|
||||
providers: [
|
||||
{ provide: 'ORIGIN_URL', useValue: location.origin }
|
||||
]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
14
templates/Angular2Spa/ClientApp/app/app.module.server.ts
Normal file
14
templates/Angular2Spa/ClientApp/app/app.module.server.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ServerModule } from '@angular/platform-server';
|
||||
import { sharedConfig } from './app.module.shared';
|
||||
|
||||
@NgModule({
|
||||
bootstrap: sharedConfig.bootstrap,
|
||||
declarations: sharedConfig.declarations,
|
||||
imports: [
|
||||
ServerModule,
|
||||
...sharedConfig.imports
|
||||
]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { UniversalModule } from 'angular2-universal';
|
||||
|
||||
import { AppComponent } from './components/app/app.component'
|
||||
import { NavMenuComponent } from './components/navmenu/navmenu.component';
|
||||
import { HomeComponent } from './components/home/home.component';
|
||||
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
|
||||
import { CounterComponent } from './components/counter/counter.component';
|
||||
|
||||
@NgModule({
|
||||
export const sharedConfig: NgModule = {
|
||||
bootstrap: [ AppComponent ],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
@@ -17,7 +17,6 @@ import { CounterComponent } from './components/counter/counter.component';
|
||||
HomeComponent
|
||||
],
|
||||
imports: [
|
||||
UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
|
||||
RouterModule.forRoot([
|
||||
{ path: '', redirectTo: 'home', pathMatch: 'full' },
|
||||
{ path: 'home', component: HomeComponent },
|
||||
@@ -26,6 +25,4 @@ import { CounterComponent } from './components/counter/counter.component';
|
||||
{ path: '**', redirectTo: 'home' }
|
||||
])
|
||||
]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
|
||||
@Component({
|
||||
@@ -8,8 +8,8 @@ import { Http } from '@angular/http';
|
||||
export class FetchDataComponent {
|
||||
public forecasts: WeatherForecast[];
|
||||
|
||||
constructor(http: Http) {
|
||||
http.get('/api/SampleData/WeatherForecasts').subscribe(result => {
|
||||
constructor(http: Http, @Inject('ORIGIN_URL') originUrl: string) {
|
||||
http.get(originUrl + '/api/SampleData/WeatherForecasts').subscribe(result => {
|
||||
this.forecasts = result.json() as WeatherForecast[];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
import 'angular2-universal-polyfills/browser';
|
||||
import 'reflect-metadata';
|
||||
import 'zone.js';
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformUniversalDynamic } from 'angular2-universal';
|
||||
import { AppModule } from './app/app.module';
|
||||
import 'bootstrap';
|
||||
const rootElemTagName = 'app'; // Update this if you change your root component selector
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { AppModule } from './app/app.module.client';
|
||||
|
||||
// Enable either Hot Module Reloading or production mode
|
||||
if (module['hot']) {
|
||||
module['hot'].accept();
|
||||
module['hot'].dispose(() => {
|
||||
// Before restarting the app, we create a new root element and dispose the old one
|
||||
const oldRootElem = document.querySelector(rootElemTagName);
|
||||
const newRootElem = document.createElement(rootElemTagName);
|
||||
const oldRootElem = document.querySelector('app');
|
||||
const newRootElem = document.createElement('app');
|
||||
oldRootElem.parentNode.insertBefore(newRootElem, oldRootElem);
|
||||
platform.destroy();
|
||||
modulePromise.then(appModule => appModule.destroy());
|
||||
});
|
||||
} else {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
// Boot the application, either now or when the DOM content is loaded
|
||||
const platform = platformUniversalDynamic();
|
||||
const bootApplication = () => { platform.bootstrapModule(AppModule); };
|
||||
if (document.readyState === 'complete') {
|
||||
bootApplication();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', bootApplication);
|
||||
}
|
||||
// Note: @ng-tools/webpack looks for the following expression when performing production
|
||||
// builds. Don't change how this line looks, otherwise you may break tree-shaking.
|
||||
const modulePromise = platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
import 'angular2-universal-polyfills';
|
||||
import 'angular2-universal-patch';
|
||||
import 'reflect-metadata';
|
||||
import 'zone.js';
|
||||
import 'rxjs/add/operator/first';
|
||||
import { enableProdMode, ApplicationRef, NgZone, ValueProvider } from '@angular/core';
|
||||
import { platformDynamicServer, PlatformState, INITIAL_CONFIG } from '@angular/platform-server';
|
||||
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformNodeDynamic } from 'angular2-universal';
|
||||
import { AppModule } from './app/app.module';
|
||||
import { AppModule } from './app/app.module.server';
|
||||
|
||||
enableProdMode();
|
||||
const platform = platformNodeDynamic();
|
||||
|
||||
export default createServerRenderer(params => {
|
||||
return new Promise<RenderResult>((resolve, reject) => {
|
||||
const requestZone = Zone.current.fork({
|
||||
name: 'angular-universal request',
|
||||
properties: {
|
||||
baseUrl: '/',
|
||||
requestUrl: params.url,
|
||||
originUrl: params.origin,
|
||||
preboot: false,
|
||||
document: '<app></app>'
|
||||
},
|
||||
onHandleError: (parentZone, currentZone, targetZone, error) => {
|
||||
// If any error occurs while rendering the module, reject the whole operation
|
||||
reject(error);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
const providers = [
|
||||
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
|
||||
{ provide: 'ORIGIN_URL', useValue: params.origin }
|
||||
];
|
||||
|
||||
return requestZone.run<Promise<string>>(() => platform.serializeModule(AppModule)).then(html => {
|
||||
resolve({ html: html });
|
||||
}, reject);
|
||||
return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
|
||||
const appRef = moduleRef.injector.get(ApplicationRef);
|
||||
const state = moduleRef.injector.get(PlatformState);
|
||||
const zone = moduleRef.injector.get(NgZone);
|
||||
|
||||
return new Promise<RenderResult>((resolve, reject) => {
|
||||
zone.onError.subscribe(errorInfo => 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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Load required polyfills and testing libraries
|
||||
import 'angular2-universal-polyfills';
|
||||
import 'reflect-metadata';
|
||||
import 'zone.js';
|
||||
import 'zone.js/dist/long-stack-trace-zone';
|
||||
import 'zone.js/dist/proxy.js';
|
||||
import 'zone.js/dist/sync-test';
|
||||
|
||||
@@ -5,58 +5,56 @@
|
||||
"test": "karma start ClientApp/test/karma.conf.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/common": "^2.4.5",
|
||||
"@angular/compiler": "^2.4.5",
|
||||
"@angular/core": "^2.4.5",
|
||||
"@angular/forms": "^2.4.5",
|
||||
"@angular/http": "^2.4.5",
|
||||
"@angular/platform-browser": "^2.4.5",
|
||||
"@angular/platform-browser-dynamic": "^2.4.5",
|
||||
"@angular/platform-server": "^2.4.5",
|
||||
"@angular/router": "^3.4.5",
|
||||
"@types/node": "^6.0.42",
|
||||
"angular2-platform-node": "~2.0.11",
|
||||
"angular2-template-loader": "^0.6.2",
|
||||
"angular2-universal": "^2.1.0-rc.1",
|
||||
"angular2-universal-patch": "^0.2.1",
|
||||
"angular2-universal-polyfills": "^2.1.0-rc.1",
|
||||
"aspnet-prerendering": "^2.0.0",
|
||||
"aspnet-webpack": "^1.0.17",
|
||||
"awesome-typescript-loader": "^3.0.0",
|
||||
"bootstrap": "^3.3.7",
|
||||
"css": "^2.2.1",
|
||||
"css-loader": "^0.25.0",
|
||||
"es6-shim": "^0.35.1",
|
||||
"event-source-polyfill": "^0.0.7",
|
||||
"expose-loader": "^0.7.1",
|
||||
"extract-text-webpack-plugin": "^2.0.0-rc",
|
||||
"file-loader": "^0.9.0",
|
||||
"html-loader": "^0.4.4",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"jquery": "^2.2.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"preboot": "^4.5.2",
|
||||
"raw-loader": "^0.5.1",
|
||||
"rxjs": "^5.0.1",
|
||||
"style-loader": "^0.13.1",
|
||||
"to-string-loader": "^1.1.5",
|
||||
"typescript": "^2.2.1",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^2.2.0",
|
||||
"webpack-hot-middleware": "^2.12.2",
|
||||
"webpack-merge": "^0.14.1",
|
||||
"zone.js": "^0.7.6"
|
||||
"@angular/animations": "4.1.2",
|
||||
"@angular/common": "4.1.2",
|
||||
"@angular/compiler": "4.1.2",
|
||||
"@angular/core": "4.1.2",
|
||||
"@angular/forms": "4.1.2",
|
||||
"@angular/http": "4.1.2",
|
||||
"@angular/platform-browser": "4.1.2",
|
||||
"@angular/platform-browser-dynamic": "4.1.2",
|
||||
"@angular/platform-server": "4.1.2",
|
||||
"@angular/router": "4.1.2",
|
||||
"@types/node": "7.0.18",
|
||||
"angular2-template-loader": "0.6.2",
|
||||
"aspnet-prerendering": "^2.0.5",
|
||||
"aspnet-webpack": "^1.0.29",
|
||||
"awesome-typescript-loader": "3.1.3",
|
||||
"bootstrap": "3.3.7",
|
||||
"css": "2.2.1",
|
||||
"css-loader": "0.28.1",
|
||||
"es6-shim": "0.35.3",
|
||||
"event-source-polyfill": "0.0.9",
|
||||
"expose-loader": "0.7.3",
|
||||
"extract-text-webpack-plugin": "2.1.0",
|
||||
"file-loader": "0.11.1",
|
||||
"html-loader": "0.4.5",
|
||||
"isomorphic-fetch": "2.2.1",
|
||||
"jquery": "3.2.1",
|
||||
"json-loader": "0.5.4",
|
||||
"preboot": "4.5.2",
|
||||
"raw-loader": "0.5.1",
|
||||
"reflect-metadata": "0.1.10",
|
||||
"rxjs": "5.4.0",
|
||||
"style-loader": "0.17.0",
|
||||
"to-string-loader": "1.1.5",
|
||||
"typescript": "2.3.2",
|
||||
"url-loader": "0.5.8",
|
||||
"webpack": "2.5.1",
|
||||
"webpack-hot-middleware": "2.18.0",
|
||||
"webpack-merge": "4.1.0",
|
||||
"zone.js": "0.8.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^3.4.34",
|
||||
"@types/jasmine": "^2.5.37",
|
||||
"chai": "^3.5.0",
|
||||
"jasmine-core": "^2.5.2",
|
||||
"karma": "^1.3.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-chrome-launcher": "^2.0.0",
|
||||
"karma-cli": "^1.0.1",
|
||||
"karma-jasmine": "^1.0.2",
|
||||
"karma-webpack": "^1.8.0"
|
||||
"@types/chai": "3.5.2",
|
||||
"@types/jasmine": "2.5.47",
|
||||
"chai": "3.5.0",
|
||||
"jasmine-core": "2.6.1",
|
||||
"karma": "1.7.0",
|
||||
"karma-chai": "0.1.0",
|
||||
"karma-chrome-launcher": "2.1.1",
|
||||
"karma-cli": "1.0.1",
|
||||
"karma-jasmine": "1.1.0",
|
||||
"karma-webpack": "2.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,15 @@ module.exports = (env) => {
|
||||
},
|
||||
entry: {
|
||||
vendor: [
|
||||
'@angular/animations',
|
||||
'@angular/common',
|
||||
'@angular/compiler',
|
||||
'@angular/core',
|
||||
'@angular/forms',
|
||||
'@angular/http',
|
||||
'@angular/platform-browser',
|
||||
'@angular/platform-browser-dynamic',
|
||||
'@angular/router',
|
||||
'@angular/platform-server',
|
||||
'angular2-universal',
|
||||
'angular2-universal-polyfills',
|
||||
'bootstrap',
|
||||
'bootstrap/dist/css/bootstrap.css',
|
||||
'es6-shim',
|
||||
@@ -43,6 +42,7 @@ module.exports = (env) => {
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)
|
||||
new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/11580
|
||||
new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/14898
|
||||
new webpack.IgnorePlugin(/^vertx$/) // Workaround for https://github.com/stefanpenner/es6-promise/issues/100
|
||||
]
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user