Fixed AoT Build

This commit is contained in:
Art Lowel
2018-01-23 15:16:22 +01:00
parent 107a0736c6
commit 962d87173e
8 changed files with 181 additions and 155 deletions

4
src/main.server.aot.ts Normal file
View File

@@ -0,0 +1,4 @@
import { startServer } from './server';
import { ServerAppModuleNgFactory } from './modules/app/server-app.module.ngfactory';
startServer(ServerAppModuleNgFactory);

View File

@@ -1,134 +1,4 @@
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import 'rxjs/Rx';
import * as fs from 'fs';
import * as pem from 'pem';
import * as https from 'https';
import * as morgan from 'morgan';
import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as compression from 'compression';
import * as cookieParser from 'cookie-parser';
import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { startServer } from './server';
import { ServerAppModule } from './modules/app/server-app.module';
import { ROUTES } from './routes';
import { ENV_CONFIG } from './config';
const app = express();
const port = ENV_CONFIG.ui.port ? ENV_CONFIG.ui.port : 80;
if (ENV_CONFIG.production) {
enableProdMode();
app.use(compression());
}
app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser.json());
app.engine('html', ngExpressEngine({
bootstrap: ServerAppModule
}));
app.set('view engine', 'html');
app.set('views', 'src');
function cacheControl(req, res, next) {
// instruct browser to revalidate
res.header('Cache-Control', ENV_CONFIG.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) {
function onHandleError(parentZoneDelegate, currentZone, targetZone, error) {
console.warn('Error in SSR, serving for direct CSR');
res.sendFile('index.csr.html', { root: './src' });
}
if (ENV_CONFIG.universal.preboot) {
Zone.current.fork({ name: 'CSR fallback', onHandleError }).run(() => {
res.render('../dist/index', {
req,
res,
preboot: ENV_CONFIG.universal.preboot,
async: ENV_CONFIG.universal.async,
time: ENV_CONFIG.universal.time,
baseUrl: ENV_CONFIG.ui.nameSpace,
originUrl: ENV_CONFIG.ui.baseUrl,
requestUrl: req.originalUrl
});
});
} else {
console.log('Universal off, serving for direct CSR');
res.sendFile('index.csr.html', { root: './src' });
}
}
ROUTES.forEach((route: string) => {
app.get(route, ngApp);
});
function serverStarted() {
console.log(`[${new Date().toTimeString()}] Listening at ${ENV_CONFIG.ui.baseUrl}`);
}
function createHttpsServer(keys) {
https.createServer({
key: keys.serviceKey,
cert: keys.certificate
}, app).listen(port, ENV_CONFIG.ui.host, () => {
serverStarted();
});
}
if (ENV_CONFIG.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(port, ENV_CONFIG.ui.host, () => {
serverStarted();
});
}
startServer(ServerAppModule);

133
src/server.ts Normal file
View File

@@ -0,0 +1,133 @@
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import 'rxjs/Rx';
import * as fs from 'fs';
import * as pem from 'pem';
import * as https from 'https';
import * as morgan from 'morgan';
import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as compression from 'compression';
import * as cookieParser from 'cookie-parser';
import { enableProdMode, NgModuleFactory, Type } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { ROUTES } from './routes';
import { ENV_CONFIG } from './config';
export function startServer(bootstrap: Type<{}> | NgModuleFactory<{}>) {
const app = express();
const port = ENV_CONFIG.ui.port ? ENV_CONFIG.ui.port : 80;
if (ENV_CONFIG.production) {
enableProdMode();
app.use(compression());
}
app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser.json());
app.engine('html', ngExpressEngine({
bootstrap: bootstrap
}));
app.set('view engine', 'html');
app.set('views', 'src');
function cacheControl(req, res, next) {
// instruct browser to revalidate
res.header('Cache-Control', ENV_CONFIG.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) {
function onHandleError(parentZoneDelegate, currentZone, targetZone, error) {
console.warn('Error in SSR, serving for direct CSR');
res.sendFile('index.csr.html', { root: './src' });
}
if (ENV_CONFIG.universal.preboot) {
Zone.current.fork({ name: 'CSR fallback', onHandleError }).run(() => {
res.render('../dist/index', {
req,
res,
preboot: ENV_CONFIG.universal.preboot,
async: ENV_CONFIG.universal.async,
time: ENV_CONFIG.universal.time,
baseUrl: ENV_CONFIG.ui.nameSpace,
originUrl: ENV_CONFIG.ui.baseUrl,
requestUrl: req.originalUrl
});
});
} else {
console.log('Universal off, serving for direct CSR');
res.sendFile('index.csr.html', { root: './src' });
}
}
ROUTES.forEach((route: string) => {
app.get(route, ngApp);
});
function serverStarted() {
console.log(`[${new Date().toTimeString()}] Listening at ${ENV_CONFIG.ui.baseUrl}`);
}
function createHttpsServer(keys) {
https.createServer({
key: keys.serviceKey,
cert: keys.certificate
}, app).listen(port, ENV_CONFIG.ui.host, () => {
serverStarted();
});
}
if (ENV_CONFIG.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(port, ENV_CONFIG.ui.host, () => {
serverStarted();
});
}}

View File

@@ -0,0 +1,7 @@
{
"extends": "./tsconfig.server.json",
"angularCompilerOptions": {
"entryModule": "./modules/app/server-app.module#ServerAppModule"
},
"exclude": []
}

View File

@@ -7,13 +7,13 @@
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"noEmit": true,
"noEmitHelpers": true,
"importHelpers": true,
"noImplicitAny": false,
"strictNullChecks": false,
"skipDefaultLibCheck": true,
"pretty": true,
"baseUrl": ".",
"paths": {},
"typeRoots": [
"node_modules/@types"
],
@@ -22,23 +22,23 @@
"node"
],
"lib": [
"dom",
"es6",
"es2015",
"es2016",
"dom"
"es2017"
]
},
"exclude": [
"node_modules",
"dist",
"src/**/*.spec.ts",
"src/**/*.e2e.ts"
"src/**/*.e2e.ts",
"src/main.server.aot.ts"
],
"compileOnSave": false,
"buildOnSave": false,
"atom": {
"rewriteTsconfig": false
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"preserveWhitespaces": false
}
}

View File

@@ -1,7 +1,7 @@
const webpackMerge = require('webpack-merge');
const commonPartial = require('./webpack/webpack.common');
const clientPartial = require('./webpack/webpack.client');
const serverPartial = require('./webpack/webpack.server');
const { getServerWebpackPartial } = require('./webpack/webpack.server');
const prodPartial = require('./webpack/webpack.prod');
const {
@@ -15,6 +15,8 @@ module.exports = function(options, webpackOptions) {
console.log(`Running build for ${options.client ? 'client' : 'server'} with AoT Compilation`)
}
let serverPartial = getServerWebpackPartial(options.aot);
let serverConfig = webpackMerge({}, commonPartial, serverPartial, {
plugins: [
getAotPlugin('server', !!options.aot)

View File

@@ -3,7 +3,7 @@ const {
} = require('./helpers');
const {
AotPlugin
AngularCompilerPlugin
} = require('@ngtools/webpack');
const tsconfigs = {
@@ -11,6 +11,11 @@ const tsconfigs = {
server: root('./src/tsconfig.server.json')
};
const aotTsconfigs = {
client: root('./src/tsconfig.browser.json'),
server: root('./src/tsconfig.server.aot.json')
};
/**
* Generates a AotPlugin for @ngtools/webpack
*
@@ -19,8 +24,8 @@ const tsconfigs = {
* @returns {AotPlugin} Configuration of AotPlugin
*/
function getAotPlugin(platform, aot) {
return new AotPlugin({
tsConfigPath: tsconfigs[platform],
return new AngularCompilerPlugin({
tsConfigPath: aot ? aotTsconfigs[platform] : tsconfigs[platform],
skipCodeGeneration: !aot
});
}

View File

@@ -5,15 +5,20 @@ const {
} = require('./helpers');
module.exports = {
entry: root('./src/main.server.ts'),
output: {
filename: 'server.js'
},
target: 'node',
externals: [nodeExternals({
whitelist: [
/@angular/,
/@ng/,
/ngx/]
})],
getServerWebpackPartial: function (aot) {
const entry = aot ? root('./src/main.server.aot.ts') : root('./src/main.server.ts');
return {
entry: entry,
output: {
filename: 'server.js'
},
target: 'node',
externals: [nodeExternals({
whitelist: [
/@angular/,
/@ng/,
/ngx/]
})],
}
}
};