diff --git a/server.ts b/server.ts
index 131b6bb4ae..f1e8e1943f 100644
--- a/server.ts
+++ b/server.ts
@@ -1,3 +1,20 @@
+/**
+ * *** NOTE ON IMPORTING FROM ANGULAR AND NGUNIVERSAL IN THIS FILE ***
+ *
+ * If your application uses third-party dependencies, you'll need to
+ * either use Webpack or the Angular CLI's `bundleDependencies` feature
+ * in order to adequately package them for use on the server without a
+ * node_modules directory.
+ *
+ * However, due to the nature of the CLI's `bundleDependencies`, importing
+ * Angular in this file will create a different instance of Angular than
+ * the version in the compiled application code. This leads to unavoidable
+ * conflicts. Therefore, please do not explicitly import from @angular or
+ * @nguniversal in this file. You can export any needed resources
+ * from your application's main.server.ts file, as seen below with the
+ * import for `ngExpressEngine`.
+ */
+
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import 'rxjs';
@@ -10,148 +27,154 @@ import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as compression from 'compression';
import * as cookieParser from 'cookie-parser';
+import { join } from 'path';
import { enableProdMode, NgModuleFactory, Type } from '@angular/core';
-import { ngExpressEngine } from '@nguniversal/express-engine';
-
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
import { environment } from './src/environments/environment';
-export function startServer(bootstrap: Type<{}> | NgModuleFactory<{}>) {
- const app = express();
+const DIST_FOLDER = join(process.cwd(), 'dist/browser');
- if (environment.production) {
- enableProdMode();
- app.use(compression());
- }
+// * NOTE :: leave this as require() since this file is built Dynamically from webpack
+const { ServerAppModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap } = require('./dist/server/main');
- app.use(morgan('dev'));
+const app = express();
- app.use(cookieParser());
- app.use(bodyParser.json());
+if (environment.production) {
+ enableProdMode();
+ app.use(compression());
+}
- app.engine('html', (_, options, callback) =>
- ngExpressEngine({
- bootstrap: bootstrap,
- providers: [
- {
- provide: REQUEST,
- useValue: (options as any).req,
- },
- {
- provide: RESPONSE,
- useValue: (options as any).req.res,
- },
- ],
- })(_, (options as any), callback)
- );
+app.use(morgan('dev'));
- app.set('view engine', 'ejs');
- app.set('view engine', 'html');
- app.set('views', 'src');
+app.use(cookieParser());
+app.use(bodyParser.json());
- function cacheControl(req, res, next) {
- // instruct browser to revalidate
- res.header('Cache-Control', environment.cache.control || 'max-age=60');
- next();
- }
+app.engine('html', (_, options, callback) =>
+ ngExpressEngine({
+ bootstrap: ServerAppModuleNgFactory,
+ providers: [
+ {
+ provide: REQUEST,
+ useValue: (options as any).req,
+ },
+ {
+ provide: RESPONSE,
+ useValue: (options as any).req.res,
+ },
+ provideModuleMap(LAZY_MODULE_MAP)
+ ],
+ })(_, (options as any), callback)
+);
- app.use('/', cacheControl, express.static('dist', { index: false }));
+app.set('view engine', 'ejs');
+app.set('view engine', 'html');
+app.set('views', DIST_FOLDER);
+
+function cacheControl(req, res, next) {
+ // instruct browser to revalidate
+ res.header('Cache-Control', environment.cache.control || 'max-age=60');
+ next();
+}
+
+app.use('/', cacheControl, express.static('dist', { index: false }));
// TODO: either remove or update mock backend
// app.get('/data.json', serverApi);
// app.use('/api', createMockApi());
- function ngApp(req, res) {
- const dspace = {
- originalRequest: {
- headers: req.headers,
- body: req.body,
- method: req.method,
- params: req.params,
- reportProgress: req.reportProgress,
- withCredentials: req.withCredentials,
- responseType: req.responseType,
- urlWithParams: req.urlWithParams
- }
- };
-
- function onHandleError(parentZoneDelegate, currentZone, targetZone, error) {
- if (!res._headerSent) {
- console.warn('Error in SSR, serving for direct CSR. Error details : ', error);
- res.sendFile('index.csr.html', { root: './src' });
- }
+function ngApp(req, res) {
+ const dspace = {
+ originalRequest: {
+ headers: req.headers,
+ body: req.body,
+ method: req.method,
+ params: req.params,
+ reportProgress: req.reportProgress,
+ withCredentials: req.withCredentials,
+ responseType: req.responseType,
+ urlWithParams: req.urlWithParams
}
+ };
- if (environment.universal.preboot) {
- Zone.current.fork({ name: 'CSR fallback', onHandleError }).run(() => {
- res.render('../dist/index.html', {
- req,
- res,
- preboot: environment.universal.preboot,
- async: environment.universal.async,
- time: environment.universal.time,
- baseUrl: environment.ui.nameSpace,
- originUrl: environment.ui.baseUrl,
- requestUrl: req.originalUrl
- });
- });
- } else {
- console.log('Universal off, serving for direct CSR');
- res.render('index-csr.ejs', {
- root: './src',
- scripts: ``
- });
+ function onHandleError(parentZoneDelegate, currentZone, targetZone, error) {
+ if (!res._headerSent) {
+ console.warn('Error in SSR, serving for direct CSR. Error details : ', error);
+ res.sendFile('index.csr.html', { root: DIST_FOLDER });
}
}
- function serverStarted() {
- console.log(`[${new Date().toTimeString()}] Listening at ${environment.ui.baseUrl}`);
- }
-
- function createHttpsServer(keys) {
- https.createServer({
- key: keys.serviceKey,
- cert: keys.certificate
- }, app).listen(environment.ui.port, environment.ui.host, () => {
- serverStarted();
+ if (environment.universal.preboot) {
+ Zone.current.fork({ name: 'CSR fallback', onHandleError }).run(() => {
+ res.render(DIST_FOLDER, {
+ req,
+ res,
+ preboot: environment.universal.preboot,
+ async: environment.universal.async,
+ time: environment.universal.time,
+ baseUrl: environment.ui.nameSpace,
+ originUrl: environment.ui.baseUrl,
+ requestUrl: req.originalUrl
+ });
});
- }
-
- if (environment.ui.ssl) {
- let serviceKey;
- try {
- serviceKey = fs.readFileSync('./config/ssl/key.pem');
- } catch (e) {
- console.warn('Service key not found at ./config/ssl/key.pem');
- }
-
- let certificate;
- try {
- certificate = fs.readFileSync('./config/ssl/cert.pem');
- } catch (e) {
- console.warn('Certificate not found at ./config/ssl/key.pem');
- }
-
- if (serviceKey && certificate) {
- createHttpsServer({
- serviceKey: serviceKey,
- certificate: certificate
- });
- } else {
-
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
-
- pem.createCertificate({
- days: 1,
- selfSigned: true
- }, (error, keys) => {
- createHttpsServer(keys);
- });
- }
} else {
- app.listen(environment.ui.port, environment.ui.host, () => {
- serverStarted();
+ console.log('Universal off, serving for direct CSR');
+ res.render('index-csr.ejs', {
+ root: DIST_FOLDER,
+ scripts: ``
});
- }}
+ }
+}
+
+app.get('*.*', ngApp);
+
+function serverStarted() {
+ console.log(`[${new Date().toTimeString()}] Listening at ${environment.ui.baseUrl}`);
+}
+
+function createHttpsServer(keys) {
+ https.createServer({
+ key: keys.serviceKey,
+ cert: keys.certificate
+ }, app).listen(environment.ui.port, environment.ui.host, () => {
+ serverStarted();
+ });
+}
+
+if (environment.ui.ssl) {
+ let serviceKey;
+ try {
+ serviceKey = fs.readFileSync('./config/ssl/key.pem');
+ } catch (e) {
+ console.warn('Service key not found at ./config/ssl/key.pem');
+ }
+
+ let certificate;
+ try {
+ certificate = fs.readFileSync('./config/ssl/cert.pem');
+ } catch (e) {
+ console.warn('Certificate not found at ./config/ssl/key.pem');
+ }
+
+ if (serviceKey && certificate) {
+ createHttpsServer({
+ serviceKey: serviceKey,
+ certificate: certificate
+ });
+ } else {
+
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
+
+ pem.createCertificate({
+ days: 1,
+ selfSigned: true
+ }, (error, keys) => {
+ createHttpsServer(keys);
+ });
+ }
+} else {
+ app.listen(environment.ui.port, environment.ui.host, () => {
+ serverStarted();
+ });
+}