@nxarch/nest-nguniversal
Version:
A NestJS library to serve your NestJS Angular Universal project
112 lines (111 loc) • 4.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCacheOptions = exports.setupUniversal = void 0;
const tslib_1 = require("tslib");
const common_1 = require("@nestjs/common");
const express = require("express");
const fs_1 = require("fs");
const path_1 = require("path");
require("reflect-metadata");
require("zone.js/dist/zone-node");
const cache_key_by_original_url_generator_1 = require("../cache/cache-key-by-original-url.generator");
const utilities_1 = require("./utilities");
const DEFAULT_CACHE_EXPIRATION_TIME = 60000; // 60 seconds
function setupUniversal(app, ngOptions, ngStorageProvider) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const logger = new common_1.Logger('AngularUniversalModule');
const cacheOptions = getCacheOptions(ngOptions);
app.engine('html', (_, options, callback) => tslib_1.__awaiter(this, void 0, void 0, function* () {
let cacheKey;
if (cacheOptions.isEnabled) {
const cacheKeyGenerator = cacheOptions.keyGenerator;
cacheKey = cacheKeyGenerator.generateCacheKey(options.req);
const cacheHtml = yield ngStorageProvider.get(cacheKey, options.req);
if (cacheHtml) {
callback(null, cacheHtml);
return;
}
}
let mainSsr;
if (typeof ngOptions.bootstrap === 'string') {
if (typeof __non_webpack_require__ !== 'function')
throw Error('Make sure to use webpack in order to use string type bootstrap property');
// remove webpack require cache in order to ensure reload of app ssr bundle
// will decrease server side rendering; only use during development!
const shouldRemoveCache = !(0, utilities_1.isNil)(process.env.REMOVE_WEBPACK_CACHE)
? process.env.REMOVE_WEBPACK_CACHE === 'true'
: process.env.NODE_ENV === 'development';
if (shouldRemoveCache) {
removeUiBundlesFromCache(ngOptions.bootstrap);
}
mainSsr = __non_webpack_require__(ngOptions.bootstrap);
}
else {
mainSsr = yield ngOptions.bootstrap();
}
const { AppSsrModule, ngExpressEngine } = mainSsr;
ngExpressEngine({
bootstrap: AppSsrModule || ngOptions.bootstrap,
inlineCriticalCss: ngOptions.inlineCriticalCss,
providers: [
{
provide: 'serverUrl',
useValue: `${options.req.protocol}://${options.req.get('host')}`,
},
...(ngOptions.extraProviders || []),
],
})(_, options, (err, html) => {
if (err && ngOptions.errorHandler) {
return ngOptions.errorHandler({ err, html, renderCallback: callback });
}
if (err || !html) {
logger.error(err);
return callback(err);
}
if (cacheOptions.isEnabled && cacheKey) {
html = ngStorageProvider.set(cacheKey, html, options.req, cacheOptions.expiresIn) || html;
}
callback(null, html);
});
}));
app.set('view engine', 'html');
app.set('views', ngOptions.viewsPath);
// Serve static files
app.get(ngOptions.rootStaticPath, express.static(ngOptions.viewsPath, {
maxAge: 600,
setHeaders: ngOptions.staticAssetsHeaders,
}));
});
}
exports.setupUniversal = setupUniversal;
function getCacheOptions(ngOptions) {
if (!ngOptions.cache) {
return {
isEnabled: false,
};
}
if (typeof ngOptions.cache !== 'object') {
return {
isEnabled: true,
expiresIn: DEFAULT_CACHE_EXPIRATION_TIME,
keyGenerator: new cache_key_by_original_url_generator_1.CacheKeyByOriginalUrlGenerator(),
};
}
return {
isEnabled: true,
expiresIn: ngOptions.cache.expiresIn || DEFAULT_CACHE_EXPIRATION_TIME,
keyGenerator: ngOptions.cache.keyGenerator || new cache_key_by_original_url_generator_1.CacheKeyByOriginalUrlGenerator(),
};
}
exports.getCacheOptions = getCacheOptions;
function removeUiBundlesFromCache(mainJsPath) {
const uiFolder = (0, path_1.dirname)(mainJsPath);
(0, fs_1.readdir)(uiFolder, (err, files) => {
files.forEach((file) => {
const absolutePath = (0, path_1.join)(uiFolder, file);
if (file.includes('.js') && !!__non_webpack_require__.cache[absolutePath]) {
delete __non_webpack_require__.cache[absolutePath];
}
});
});
}