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
const compression = require('compression');
15
app.use(compression());
16
const PORT = process.env.PORT || 3000;
17
const DIST_FOLDER = join(process.cwd(), 'dist');
18

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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