@@ -7,31 +7,155 @@ import { join } from 'path';
77import { AppServerModule } from './src/main.server' ;
88import { APP_BASE_HREF } from '@angular/common' ;
99import { existsSync } from 'fs' ;
10+ import { REQUEST , RESPONSE } from '@nguniversal/express-engine/tokens' ;
11+ import { NgxRequest , NgxResponse } from '@gorniv/ngx-universal' ;
12+ import * as compression from 'compression' ;
13+ import * as cookieparser from 'cookie-parser' ;
14+ import { exit } from 'process' ;
15+ // for debug
16+ require ( 'source-map-support' ) . install ( ) ;
17+
18+ // for tests
19+ const test = process . env [ 'TEST' ] === 'true' ;
20+
21+ // ssr DOM
22+ const domino = require ( 'domino' ) ;
23+ const fs = require ( 'fs' ) ;
24+ const path = require ( 'path' ) ;
25+ // index from browser build!
26+ const template = fs . readFileSync ( path . join ( '.' , 'dist' , 'index.html' ) ) . toString ( ) ;
27+ // for mock global window by domino
28+ const win = domino . createWindow ( template ) ;
29+ // from server build
30+ const files = fs . readdirSync ( `${ process . cwd ( ) } /dist-server` ) ;
31+ // mock
32+ global [ 'window' ] = win ;
33+ // not implemented property and functions
34+ Object . defineProperty ( win . document . body . style , 'transform' , {
35+ value : ( ) => {
36+ return {
37+ enumerable : true ,
38+ configurable : true ,
39+ } ;
40+ } ,
41+ } ) ;
42+ // mock documnet
43+ global [ 'document' ] = win . document ;
44+ // othres mock
45+ global [ 'CSS' ] = null ;
46+ // global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
47+ global [ 'Prism' ] = null ;
1048
1149// The Express app is exported so that it can be used by serverless Functions.
1250export function app ( ) {
1351 const server = express ( ) ;
1452 const distFolder = join ( process . cwd ( ) , 'dist' ) ;
15- const indexHtml = existsSync ( join ( distFolder , 'index.original.html' ) ) ? 'index.original.html' : 'index' ;
53+ const indexHtml = existsSync ( join ( distFolder , 'index.original.html' ) )
54+ ? 'index.original.html'
55+ : 'index' ;
56+
57+ // redirects!
58+ const redirectowww = false ;
59+ const redirectohttps = false ;
60+ const wwwredirecto = true ;
61+ server . use ( ( req , res , next ) => {
62+ // for domain/index.html
63+ if ( req . url === '/index.html' ) {
64+ res . redirect ( 301 , 'https://' + req . hostname ) ;
65+ }
66+
67+ // check if it is a secure (https) request
68+ // if not redirect to the equivalent https url
69+ if (
70+ redirectohttps &&
71+ req . headers [ 'x-forwarded-proto' ] !== 'https' &&
72+ req . hostname !== 'localhost'
73+ ) {
74+ // special for robots.txt
75+ if ( req . url === '/robots.txt' ) {
76+ next ( ) ;
77+ return ;
78+ }
79+ res . redirect ( 301 , 'https://' + req . hostname + req . url ) ;
80+ }
81+
82+ // www or not
83+ if ( redirectowww && ! req . hostname . startsWith ( 'www.' ) ) {
84+ res . redirect ( 301 , 'https://www.' + req . hostname + req . url ) ;
85+ }
86+
87+ // www or not
88+ if ( wwwredirecto && req . hostname . startsWith ( 'www.' ) ) {
89+ const host = req . hostname . slice ( 4 , req . hostname . length ) ;
90+ res . redirect ( 301 , 'https://' + host + req . url ) ;
91+ }
1692
93+ // for test
94+ if ( test && req . url === '/test/exit' ) {
95+ res . send ( 'exit' ) ;
96+ exit ( 0 ) ;
97+ return ;
98+ }
99+
100+ next ( ) ;
101+ } ) ;
17102 // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
18- server . engine ( 'html' , ngExpressEngine ( {
19- bootstrap : AppServerModule ,
20- } ) ) ;
103+ server . engine (
104+ 'html' ,
105+ ngExpressEngine ( {
106+ bootstrap : AppServerModule ,
107+ } ) ,
108+ ) ;
21109
22110 server . set ( 'view engine' , 'html' ) ;
23111 server . set ( 'views' , distFolder ) ;
24112
25113 // Example Express Rest API endpoints
26114 // app.get('/api/**', (req, res) => { });
27115 // Serve static files from /browser
28- server . get ( '*.*' , express . static ( distFolder , {
29- maxAge : '1y'
30- } ) ) ;
116+ server . get (
117+ '*.*' ,
118+ express . static ( distFolder , {
119+ maxAge : '1y' ,
120+ } ) ,
121+ ) ;
31122
32123 // All regular routes use the Universal engine
33124 server . get ( '*' , ( req , res ) => {
34- res . render ( indexHtml , { req, providers : [ { provide : APP_BASE_HREF , useValue : req . baseUrl } ] } ) ;
125+ global [ 'navigator' ] = req [ 'headers' ] [ 'user-agent' ] ;
126+ const http =
127+ req . headers [ 'x-forwarded-proto' ] === undefined ? 'http' : req . headers [ 'x-forwarded-proto' ] ;
128+
129+ res . render ( indexHtml , {
130+ req,
131+ providers : [
132+ { provide : APP_BASE_HREF , useValue : req . baseUrl } ,
133+
134+ // for http and cookies
135+ {
136+ provide : REQUEST ,
137+ useValue : req ,
138+ } ,
139+ {
140+ provide : RESPONSE ,
141+ useValue : res ,
142+ } ,
143+ /// for cookie
144+ {
145+ provide : NgxRequest ,
146+ useValue : req ,
147+ } ,
148+ {
149+ provide : NgxResponse ,
150+ useValue : res ,
151+ } ,
152+ // for absolute path
153+ {
154+ provide : 'ORIGIN_URL' ,
155+ useValue : `${ http } ://${ req . headers . host } ` ,
156+ } ,
157+ ] ,
158+ } ) ;
35159 } ) ;
36160
37161 return server ;
@@ -42,6 +166,11 @@ function run() {
42166
43167 // Start up the Node server
44168 const server = app ( ) ;
169+ // gzip
170+ server . use ( compression ( ) ) ;
171+ // cokies
172+ server . use ( cookieparser ( ) ) ;
173+
45174 server . listen ( port , ( ) => {
46175 console . log ( `Node Express server listening on http://localhost:${ port } ` ) ;
47176 } ) ;
@@ -52,7 +181,7 @@ function run() {
52181// The below code is to ensure that the server is run only when not requiring the bundle.
53182declare const __non_webpack_require__ : NodeRequire ;
54183const mainModule = __non_webpack_require__ . main ;
55- const moduleFilename = mainModule && mainModule . filename || '' ;
184+ const moduleFilename = ( mainModule && mainModule . filename ) || '' ;
56185if ( moduleFilename === __filename || moduleFilename . includes ( 'iisnode' ) ) {
57186 run ( ) ;
58187}
0 commit comments