Skip to content

Commit 56be3f4

Browse files
committed
fix(aot): AoT & azure deployment fixes
Site now live and tested at: http://aspnetcore-angular2-universal.azurewebsites.net AoT errors fixed & azure deployment fixed
1 parent 2d108c2 commit 56be3f4

File tree

10 files changed

+176
-32
lines changed

10 files changed

+176
-32
lines changed

Client/app/app.module.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,14 @@ import { Ng2BootstrapComponent } from './containers/ng2-bootstrap-demo/ng2bootst
2020

2121
import { LinkService } from './shared/link.service';
2222
import { ConnectionResolver } from './shared/route.resolver';
23+
import { ORIGIN_URL } from './shared/constants/baseurl.constants';
2324

2425
export function createTranslateLoader(http: Http, baseHref) {
26+
console.log('\n\n\n New method? ' + baseHref);
27+
// Temporary Azure hack
28+
if (baseHref === null && typeof window !== 'undefined') {
29+
baseHref = window.location.origin;
30+
}
2531
// i18n files are in `wwwroot/assets/`
2632
return new TranslateHttpLoader(http, `${baseHref}/assets/i18n/`, '.json');
2733
}
@@ -47,7 +53,7 @@ export function createTranslateLoader(http: Http, baseHref) {
4753
loader: {
4854
provide: TranslateLoader,
4955
useFactory: (createTranslateLoader),
50-
deps: [Http, [new Inject(APP_BASE_HREF)]]
56+
deps: [Http, [ORIGIN_URL]]
5157
}
5258
}),
5359

Client/app/browser-app.module.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { NgModule } from '@angular/core';
1+
import { NgModule } from '@angular/core';
22
import { BrowserModule } from '@angular/platform-browser';
33
import { APP_BASE_HREF } from '@angular/common';
44
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
55

66
import { SignalRModule, SignalRConfiguration } from 'ng2-signalr';
77

8+
import { ORIGIN_URL } from './shared/constants/baseurl.constants';
89
import { AppModule } from './app.module';
910
import { AppComponent } from './app.component';
1011

@@ -19,6 +20,10 @@ export function createConfig(): SignalRConfiguration {
1920
return signalRConfig;
2021
}
2122

23+
export function getOriginUrl() {
24+
return window.location.origin;
25+
}
26+
2227
@NgModule({
2328
bootstrap: [AppComponent],
2429
imports: [
@@ -28,14 +33,14 @@ export function createConfig(): SignalRConfiguration {
2833
BrowserAnimationsModule,
2934
// Our Common AppModule
3035
AppModule,
31-
36+
3237
SignalRModule.forRoot(createConfig)
3338
],
3439
providers: [
3540
{
36-
// We need this for our
37-
provide: APP_BASE_HREF,
38-
useValue: window.location.origin
41+
// We need this for our Http calls since they'll be using APP_BASE_HREF (since the Server requires Absolute URLs)
42+
provide: ORIGIN_URL,
43+
useFactory: (getOriginUrl)
3944
}
4045
]
4146
})

Client/app/containers/ng2-bootstrap-demo/ng2bootstrap.component.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
export class Ng2BootstrapComponent {
88

99
public oneAtATime: boolean = true;
10-
public items: Array<string> = ['Item 1', 'Item 2', 'Item 3'];
10+
public items = ['Item 1', 'Item 2', 'Item 3'];
1111

12-
public status: Object = {
12+
public status = {
1313
isFirstOpen: true,
14-
isFirstDisabled: false
14+
isFirstDisabled: false,
15+
open: false
1516
};
1617

17-
public groups: Array<any> = [
18+
public groups = [
1819
{
1920
title: 'Angular is neato gang!',
2021
content: 'ASP.NET Core is too :)'

Client/app/containers/users/users.component.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { APP_BASE_HREF } from '@angular/common';
77

88
import { Http, URLSearchParams } from '@angular/http';
9+
import { ORIGIN_URL } from '../../shared/constants/baseurl.constants';
910

1011
@Component({
1112
selector: 'fetchdata',
@@ -33,21 +34,21 @@ export class UsersComponent implements OnInit {
3334
// Use "constructor"s only for dependency injection
3435
constructor(
3536
private http: Http,
36-
@Inject(APP_BASE_HREF) private baseHref: string
37+
@Inject(ORIGIN_URL) private baseUrl: string
3738
) { }
3839

3940
// Here you want to handle anything with @Input()'s @Output()'s
4041
// Data retrieval / etc - this is when the Component is "ready" and wired up
4142
ngOnInit() {
4243
this.newUserName = "";
43-
this.http.get(`${this.baseHref}/api/user/all`).map(res => res.json()).subscribe(result => {
44+
this.http.get(`${this.baseUrl}/api/user/all`).map(res => res.json()).subscribe(result => {
4445
console.log(result);
4546
this.users = result as IUser[];
4647
});
4748
}
4849

4950
deleteUser(user) {
50-
this.http.delete(`${this.baseHref}/api/user/delete/` + user.id).subscribe(result => {
51+
this.http.delete(`${this.baseUrl}/api/user/delete/` + user.id).subscribe(result => {
5152
if (result.ok) {
5253
let position = this.users.indexOf(user);
5354
this.users.splice(position, 1);
@@ -63,7 +64,7 @@ export class UsersComponent implements OnInit {
6364
urlSearchParams.append('id', user.id);
6465
urlSearchParams.append('name', user.name);
6566

66-
this.http.put(`${this.baseHref}/api/user/update`, urlSearchParams).subscribe(result => {
67+
this.http.put(`${this.baseUrl}/api/user/update`, urlSearchParams).subscribe(result => {
6768
if (!result.ok) {
6869
alert("There was an issue, Could not edit user");
6970
}
@@ -74,7 +75,7 @@ export class UsersComponent implements OnInit {
7475
let urlSearchParams = new URLSearchParams();
7576
urlSearchParams.append('name', newUserName);
7677

77-
this.http.post(`${this.baseHref}/api/user/insert`, urlSearchParams).subscribe(result => {
78+
this.http.post(`${this.baseUrl}/api/user/insert`, urlSearchParams).subscribe(result => {
7879
if (result.ok) {
7980
this.users.push(result.json());
8081
this.newUserName = "";
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { InjectionToken } from '@angular/core';
2+
3+
export const ORIGIN_URL = new InjectionToken<string>('ORIGIN_URL');

Client/main.server.aot.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { enableProdMode } from '@angular/core';
33
import { INITIAL_CONFIG } from '@angular/platform-server';
44
import { APP_BASE_HREF } from '@angular/common';
55
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
6+
7+
import { ORIGIN_URL } from './app/shared/constants/baseurl.constants';
68
// Grab the (Node) server-specific NgModule
79
import { ServerAppModuleNgFactory } from './ngfactory/app/server-app.module.ngfactory';
810
// Temporary * the engine will be on npm soon (`@universal/ng-aspnetcore-engine`)
9-
import { ngAspnetCoreEngine } from './polyfills/temporary-aspnetcore-engine';
11+
import { ngAspnetCoreEngineAoT } from './polyfills/temporary-aspnetcore-engine';
1012

1113
enableProdMode();
1214

@@ -21,12 +23,12 @@ export default createServerRenderer(params => {
2123
url: params.url
2224
}
2325
}, {
24-
provide: APP_BASE_HREF,
26+
provide: ORIGIN_URL,
2527
useValue: params.origin
2628
}
2729
];
2830

29-
return ngAspnetCoreEngine(providers, ServerAppModuleNgFactory).then(response => {
31+
return ngAspnetCoreEngineAoT(providers, ServerAppModuleNgFactory).then(response => {
3032
return ({
3133
html: response.html,
3234
globals: response.globals

Client/main.server.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { enableProdMode } from '@angular/core';
44
import { INITIAL_CONFIG } from '@angular/platform-server';
55
import { APP_BASE_HREF } from '@angular/common';
66
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
7+
8+
import { ORIGIN_URL } from './app/shared/constants/baseurl.constants';
79
// Grab the (Node) server-specific NgModule
810
import { ServerAppModule } from './app/server-app.module';
911
// Temporary * the engine will be on npm soon (`@universal/ng-aspnetcore-engine`)
@@ -22,7 +24,7 @@ export default createServerRenderer(params => {
2224
url: params.url
2325
}
2426
}, {
25-
provide: APP_BASE_HREF,
27+
provide: ORIGIN_URL,
2628
useValue: params.origin
2729
}
2830
];

Client/polyfills/temporary-aspnetcore-engine.ts

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
* import { ngAspnetCoreEngine } from `@ng-universal/ng-aspnetcore-engine`;
55
*/
66

7-
import { Type, NgModuleRef, ApplicationRef, Provider } from '@angular/core';
8-
import { platformDynamicServer, PlatformState } from '@angular/platform-server';
7+
import { Type, NgModuleFactory, NgModuleRef, ApplicationRef, Provider } from '@angular/core';
8+
import { platformServer, platformDynamicServer, PlatformState } from '@angular/platform-server';
99

1010
export function ngAspnetCoreEngine(
1111
providers: Provider[],
@@ -109,5 +109,112 @@ export function ngAspnetCoreEngine(
109109
reject(err);
110110
});
111111

112+
});
113+
}
114+
115+
// Temporary - these will be combined in what will be the official npm version in `angular/universal` repo
116+
117+
export function ngAspnetCoreEngineAoT(
118+
providers: Provider[],
119+
ngModule: NgModuleFactory<{}>
120+
): Promise<{ html: string, globals: { styles: string, title: string, meta: string, [key: string]: any } }> {
121+
122+
return new Promise((resolve, reject) => {
123+
124+
const platform = platformServer(providers);
125+
126+
return platform.bootstrapModuleFactory(ngModule).then((moduleRef: NgModuleRef<{}>) => {
127+
128+
const state: PlatformState = moduleRef.injector.get(PlatformState);
129+
const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
130+
131+
appRef.isStable
132+
.filter((isStable: boolean) => isStable)
133+
.first()
134+
.subscribe((stable) => {
135+
136+
// Fire the TransferCache
137+
const bootstrap = moduleRef.instance['ngOnBootstrap'];
138+
bootstrap && bootstrap();
139+
140+
// The parse5 Document itself
141+
const AST_DOCUMENT = state.getDocument();
142+
143+
// Strip out the Angular application
144+
const htmlDoc = state.renderToString();
145+
146+
const APP_HTML = htmlDoc.substring(
147+
htmlDoc.indexOf('<body>') + 6,
148+
htmlDoc.indexOf('</body>')
149+
);
150+
151+
// Strip out Styles / Meta-tags / Title
152+
const STYLES = [];
153+
const META = [];
154+
const LINKS = [];
155+
let TITLE = '';
156+
157+
const STYLES_STRING = htmlDoc.substring(
158+
htmlDoc.indexOf('<style ng-transition'),
159+
htmlDoc.lastIndexOf('</style>') + 8
160+
);
161+
162+
const HEAD = AST_DOCUMENT.head;
163+
164+
let count = 0;
165+
166+
for (let i = 0; i < HEAD.children.length; i++) {
167+
let element = HEAD.children[i];
168+
169+
if (element.name === 'title') {
170+
TITLE = element.children[0].data;
171+
}
172+
173+
// Broken after 4.0 (worked in rc)
174+
// if (element.name === 'style') {
175+
// let styleTag = '<style ';
176+
// for (let key in element.attribs) {
177+
// styleTag += `${key}="${element.attribs[key]}">`;
178+
// }
179+
180+
// styleTag += `${element.children[0].data}</style>`;
181+
// STYLES.push(styleTag);
182+
// }
183+
184+
if (element.name === 'meta') {
185+
count = count + 1;
186+
let metaString = '<meta';
187+
for (let key in element.attribs) {
188+
metaString += ` ${key}="${element.attribs[key]}"`;
189+
}
190+
META.push(`${metaString} />\n`);
191+
}
192+
193+
if (element.name === 'link') {
194+
let linkString = '<link';
195+
for (let key in element.attribs) {
196+
linkString += ` ${key}="${element.attribs[key]}"`;
197+
}
198+
LINKS.push(`${linkString} />\n`);
199+
}
200+
}
201+
202+
resolve({
203+
html: APP_HTML,
204+
globals: {
205+
styles: STYLES_STRING,
206+
title: TITLE,
207+
meta: META.join(' '),
208+
links: LINKS.join(' ')
209+
}
210+
});
211+
212+
moduleRef.destroy();
213+
214+
});
215+
}).catch(err => {
216+
reject(err);
217+
});
218+
112219
});
113220
}

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"version": "1.0.0-rc3",
44
"scripts": {
55
"test": "karma start Client/test/karma.conf.js",
6-
"postinstall": "npm run build:dev",
76
"build:dev": "webpack --progress --color",
87
"build:aot": "webpack --env.aot --env.client & webpack --env.aot --env.server"
98
},

webpack/webpack.aot.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
const { root } = require('./helpers');
1+
const { root } = require('./helpers');
22
const { AotPlugin } = require('@ngtools/webpack');
33

44
const tsconfigs = {
5-
client: root('./client/tsconfig.browser.json'),
6-
server: root('./client/tsconfig.server.json')
5+
client: root('./client/tsconfig.browser.json'),
6+
server: root('./client/tsconfig.server.json')
77
};
88

99
const aotTsconfigs = {
10-
client: root('./client/tsconfig.browser.json'),
11-
server: root('./client/tsconfig.server.aot.json')
10+
client: root('./client/tsconfig.browser.json'),
11+
server: root('./client/tsconfig.server.aot.json')
1212
};
1313

1414
/**
@@ -19,12 +19,30 @@ const aotTsconfigs = {
1919
* @returns
2020
*/
2121
function getAotPlugin(platform, aot) {
22-
return new AotPlugin({
23-
tsConfigPath: aot ? aotTsconfigs[platform] : tsconfigs[platform],
24-
skipCodeGeneration: !aot
25-
});
22+
23+
var aotPlugin = new AotPlugin({
24+
tsConfigPath: aot ? aotTsconfigs[platform] : tsconfigs[platform],
25+
skipCodeGeneration: !aot
26+
});
27+
28+
// TEMPORARY fix for Windows 10 - will be gone when fixed
29+
aotPlugin._compilerHost._resolve = function (path_to_resolve) {
30+
path_1 = require("path");
31+
path_to_resolve = aotPlugin._compilerHost._normalizePath(path_to_resolve);
32+
if (path_to_resolve[0] == '.') {
33+
return aotPlugin._compilerHost._normalizePath(path_1.join(aotPlugin._compilerHost.getCurrentDirectory(), path_to_resolve));
34+
}
35+
else if (path_to_resolve[0] == '/' || path_to_resolve.match(/^\w:\//)) {
36+
return path_to_resolve;
37+
}
38+
else {
39+
return aotPlugin._compilerHost._normalizePath(path_1.join(aotPlugin._compilerHost._basePath, path_to_resolve));
40+
}
41+
};
42+
43+
return aotPlugin;
2644
}
2745

2846
module.exports = {
29-
getAotPlugin: getAotPlugin
47+
getAotPlugin: getAotPlugin
3048
};

0 commit comments

Comments
 (0)