diff --git a/apps/rickandmorty/server.ts b/apps/rickandmorty/server.ts index 87e66ec..cb2bd0d 100644 --- a/apps/rickandmorty/server.ts +++ b/apps/rickandmorty/server.ts @@ -8,13 +8,11 @@ import { join } from 'path'; import { AppServerModule } from './src/main.server'; import { APP_BASE_HREF } from '@angular/common'; import { existsSync } from 'fs'; -import { Request } from 'express'; import { LRUCache } from '@ngx-ssr/cache'; +import { withCache } from '@ngx-ssr/cache/express'; // The Express app is exported so that it can be used by serverless Functions. export function app(): express.Express { - const cache = new LRUCache({ maxAge: 10 * 60_000, maxSize: 100 }); - const server = express(); const distFolder = join(process.cwd(), 'dist/apps/rickandmorty/browser'); const indexHtml = existsSync(join(distFolder, 'index.original.html')) @@ -24,30 +22,12 @@ export function app(): express.Express { // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine) server.engine( 'html', - async ( - filePath: string, - options: { req: Request }, - callback: ( - err?: Error | null | undefined, - html?: string | undefined - ) => void - ) => { - const fromCache = await cache.get(options.req.originalUrl).toPromise(); - - if (fromCache) { - callback(null, fromCache); - } else { - ngExpressEngine({ - bootstrap: AppServerModule, - })(filePath, options, async (err, html) => { - if (!err) { - await cache.set(options.req.originalUrl, html).toPromise(); - } - - callback(err, html); - }); - } - } + withCache( + new LRUCache({ maxAge: 10 * 60_000, maxSize: 100 }), + ngExpressEngine({ + bootstrap: AppServerModule, + }) + ) ); server.set('view engine', 'html'); diff --git a/libs/ngx-ssr/cache/express/index.ts b/libs/ngx-ssr/cache/express/index.ts new file mode 100644 index 0000000..5e7a74c --- /dev/null +++ b/libs/ngx-ssr/cache/express/index.ts @@ -0,0 +1,54 @@ +import { CacheController } from '@ngx-ssr/cache'; + +export type ExpressRenderEngine = ( + filePath: string, + options: { req: { originalUrl: string }; [key: string]: any }, + callback: (err?: Error | null | undefined, html?: string | undefined) => void +) => void; + +export function withCache( + cache: CacheController, + engine: ExpressRenderEngine +): ExpressRenderEngine { + return ( + filePath: string, + options: { req: { originalUrl: string }; [key: string]: any }, + callback: ( + err?: Error | null | undefined, + html?: string | undefined + ) => void + ) => { + function runEngine() { + engine(filePath, options, async (err, html) => { + if (!err && originalUrl) { + try { + await cache.set(originalUrl, html).toPromise(); + } catch (e) { + console.error(`Setting cache for url ${originalUrl} is failed`, e); + } + } + + callback(err, html); + }); + } + + const originalUrl = options.req?.originalUrl; + + if (!originalUrl) { + runEngine(); + return; + } + + cache + .get(originalUrl) + .toPromise() + .then((fromCache) => { + if (fromCache) { + callback(null, fromCache); + } else { + runEngine(); + } + }) + .catch(runEngine); + }; +} diff --git a/libs/ngx-ssr/cache/express/ng-package.json b/libs/ngx-ssr/cache/express/ng-package.json new file mode 100644 index 0000000..1dc0b0b --- /dev/null +++ b/libs/ngx-ssr/cache/express/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "index.ts" + } +} diff --git a/libs/ngx-ssr/cache/jest.config.js b/libs/ngx-ssr/cache/jest.config.js index 94c35b2..5287bda 100644 --- a/libs/ngx-ssr/cache/jest.config.js +++ b/libs/ngx-ssr/cache/jest.config.js @@ -1,7 +1,7 @@ module.exports = { displayName: 'ngx-ssr-cache', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], + setupFilesAfterEnv: ['/test-setup.ts'], globals: { 'ts-jest': { tsConfig: '/tsconfig.spec.json', diff --git a/libs/ngx-ssr/cache/src/test-setup.ts b/libs/ngx-ssr/cache/test-setup.ts similarity index 100% rename from libs/ngx-ssr/cache/src/test-setup.ts rename to libs/ngx-ssr/cache/test-setup.ts diff --git a/libs/ngx-ssr/cache/tsconfig.lib.json b/libs/ngx-ssr/cache/tsconfig.lib.json index 890aaeb..6846e6e 100644 --- a/libs/ngx-ssr/cache/tsconfig.lib.json +++ b/libs/ngx-ssr/cache/tsconfig.lib.json @@ -14,6 +14,7 @@ "strictMetadataEmit": true, "enableResourceInlining": true }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts"], + "exclude": [ + "test-setup.ts", "**/*.spec.ts"], "include": ["**/*.ts"] } diff --git a/libs/ngx-ssr/cache/tsconfig.spec.json b/libs/ngx-ssr/cache/tsconfig.spec.json index fd405a6..f7ea0c8 100644 --- a/libs/ngx-ssr/cache/tsconfig.spec.json +++ b/libs/ngx-ssr/cache/tsconfig.spec.json @@ -5,6 +5,8 @@ "module": "commonjs", "types": ["jest", "node"] }, - "files": ["src/test-setup.ts"], + "files": [ + "test-setup.ts" + ], "include": ["**/*.spec.ts", "**/*.d.ts"] } diff --git a/tsconfig.base.json b/tsconfig.base.json index b220f1b..8e7f46c 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -16,6 +16,7 @@ "baseUrl": ".", "paths": { "@ngx-ssr/cache": ["libs/ngx-ssr/cache/src/index.ts"], + "@ngx-ssr/cache/*": ["libs/ngx-ssr/cache/*"], "ngx-rickandmorty": ["libs/rickandmorty/api/src/index.ts"], "@ngx-ssr/rickandmorty/utils": ["libs/rickandmorty/utils/src/index.ts"], "@ngx-ssr/timeout": ["libs/ngx-ssr/timeout/src/index.ts"],