Project

General

Profile

1
import 'zone.js/dist/zone-node';
2
import 'reflect-metadata';
3
import {enableProdMode} from '@angular/core';
4

    
5
import * as express from 'express';
6
import {join} from 'path';
7
import {readFileSync} from 'fs';
8

    
9
// Faster server renders w/ Prod mode (dev mode never needed)
10
enableProdMode();
11

    
12
// Express server
13
const app = express();
14

    
15
const PORT = process.env.PORT || 4000;
16
const DIST_FOLDER = join(process.cwd(), 'dist');
17

    
18
// Our index.html we'll use as our template
19
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
20

    
21
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
22
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist/server/main');
23

    
24
// Express Engine
25
import {ngExpressEngine, RenderOptions} from '@nguniversal/express-engine';
26
// Import module map for lazy loading
27
import {provideModuleMap} from '@nguniversal/module-map-ngfactory-loader';
28
import {routes} from "./routes";
29
import * as prom from "prom-client";
30
import {REQUEST, RESPONSE} from "@nguniversal/express-engine/tokens";
31
import {renderModuleFactory} from "@angular/platform-server";
32

    
33
/*
34
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
35
app.engine('html', ngExpressEngine({
36
  bootstrap: AppServerModuleNgFactory,
37
  providers: [
38
    provideModuleMap(LAZY_MODULE_MAP)
39
  ]
40
}));
41
*/
42
// be able to get request and get domain from there
43

    
44
const register = new prom.Registry();
45

    
46
const responses = new prom.Counter({
47
  name: 'portal_http_responses_total',
48
  help: 'A counter for portal response codes for every existed or not existed pages.',
49
  labelNames: ['route', 'code'],
50
  registers: [register]
51
});
52

    
53
const histogram = new prom.Histogram({
54
  name: 'portal_http_request_duration_seconds',
55
  help: 'A Histogram for a portal. Providing information about page visits and load latency in seconds.',
56
  labelNames: ['route'],
57
  registers: [register],
58
  buckets: [0.1, 0.2, 0.5, 1, 2]
59
});
60

    
61
app.engine('html', (_, options: any, callback) => {
62
  const opts = {
63
    document: template,
64
    url: options.req.url,
65
    extraProviders: [
66
      provideModuleMap(LAZY_MODULE_MAP),
67
      {
68
        provide: REQUEST,
69
        useValue: options.req
70
      },
71
      {
72
        provide: RESPONSE,
73
        useValue: options.req.res,
74
      },
75
    ]
76
  };
77

    
78
  renderModuleFactory(AppServerModuleNgFactory, opts)
79
    .then(html => callback(null, html)
80
    );
81
});
82

    
83
app.set('view engine', 'html');
84
app.set('views', join(DIST_FOLDER, 'browser'));
85

    
86
/* - Example Express Rest API endpoints -
87
  app.get('/api/**', (req, res) => { });
88
*/
89

    
90
// Server static files from /browser
91
app.get('*.*', express.static(join(DIST_FOLDER, 'browser'), {
92
  maxAge: '1y'
93
}));
94

    
95
app.get('/metrics', (req, res) => {
96
  res.set('Content-Type', register.contentType);
97
  res.end(register.metrics());
98
});
99

    
100
// All regular routes use the Universal engine
101
app.get('*', (req, res) => {
102
  if (routes.indexOf(req.path) !== -1) {
103
    const end = histogram.startTimer({route: req.path});
104
    res.render('index', {req});
105
    res.on('finish', function () {
106
      responses.inc({route: req.path, code: res.statusCode});
107
      end();
108
    });
109
  } else {
110
    res.render('index', {req});
111
    res.on('finish', function () {
112
      responses.inc({route: '**', code: res.statusCode});
113
    });
114
  }
115
});
116

    
117
// Start up the Node server
118
app.listen(PORT, () => {
119
  console.log(`Node Express server listening on http://localhost:${PORT}`);
120
});
(7-7/10)