import 'zone.js/dist/zone-node'; import 'reflect-metadata'; import {enableProdMode} from '@angular/core'; import * as express from 'express'; import {join} from 'path'; import {readFileSync} from 'fs'; // Faster server renders w/ Prod mode (dev mode never needed) enableProdMode(); // Express server const app = express(); const compression = require('compression'); app.use(compression()); const PORT = process.env.PORT || 3000; const DIST_FOLDER = join(process.cwd(), 'dist'); // Our index.html we'll use as our template const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString(); // * NOTE :: leave this as require() since this file is built Dynamically from webpack const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist/server/main'); // Express Engine import {ngExpressEngine, RenderOptions} from '@nguniversal/express-engine'; // Import module map for lazy loading import {provideModuleMap} from '@nguniversal/module-map-ngfactory-loader'; import {routes} from "./routes"; import * as prom from "prom-client"; import {REQUEST, RESPONSE} from "@nguniversal/express-engine/tokens"; import {renderModuleFactory} from "@angular/platform-server"; /* // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine) app.engine('html', ngExpressEngine({ bootstrap: AppServerModuleNgFactory, providers: [ provideModuleMap(LAZY_MODULE_MAP) ] })); */ // be able to get request and get domain from there const register = new prom.Registry(); const responses = new prom.Counter({ name: 'portal_http_responses_total', help: 'A counter for portal response codes for every existed or not existed pages.', labelNames: ['route', 'code'], registers: [register] }); const histogram = new prom.Histogram({ name: 'portal_http_request_duration_seconds', help: 'A Histogram for a portal. Providing information about page visits and load latency in seconds.', labelNames: ['route'], registers: [register], buckets: [0.1, 0.2, 0.5, 1, 2] }); app.engine('html', (_, options: any, callback) => { const opts = { document: template, url: options.req.url, extraProviders: [ provideModuleMap(LAZY_MODULE_MAP), { provide: REQUEST, useValue: options.req }, { provide: RESPONSE, useValue: options.req.res, }, ] }; renderModuleFactory(AppServerModuleNgFactory, opts) .then(html => callback(null, html) ); }); app.set('view engine', 'html'); app.set('views', join(DIST_FOLDER, 'browser')); /* - Example Express Rest API endpoints - app.get('/api/**', (req, res) => { }); */ // Server static files from /browser app.get('*.*', express.static(join(DIST_FOLDER, 'browser'), { maxAge: '1y' })); app.get('/metrics', (req, res) => { res.set('Content-Type', register.contentType); res.end(register.metrics()); }); // All regular routes use the Universal engine app.get('*', (req, res) => { if (routes.indexOf(req.path) !== -1) { const end = histogram.startTimer({route: req.path}); res.render('index', {req}); res.on('finish', function () { responses.inc({route: req.path, code: res.statusCode}); end(); }); } else { res.render('index', {req}); res.on('finish', function () { responses.inc({route: '**', code: res.statusCode}); }); } }); // Start up the Node server app.listen(PORT, () => { console.log(`Node Express server listening on http://localhost:${PORT}`); });