UNPKG

@nxarch/nest-nguniversal

Version:

A NestJS library to serve your NestJS Angular Universal project

112 lines (111 loc) 4.93 kB
"use strict"; 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]; } }); }); }