import { logger } from './rendertron.logging.js'; import { PrerenderResult } from './rendertron.classes.prerenderresult.js'; import * as plugins from './rendertron.plugins.js'; export class PrerenderManager { public smartssrInstance: plugins.smartssr.SmartSSR; public smartrobotsInstance: plugins.smartrobots.Smartrobots; public smartsitemapInstance: plugins.smartsitemap.SmartSitemap; constructor() {} /** * starts the manager */ public async start() { this.smartssrInstance = new plugins.smartssr.SmartSSR(); this.smartrobotsInstance = new plugins.smartrobots.Smartrobots(); this.smartsitemapInstance = new plugins.smartsitemap.SmartSitemap(); } /** * stops the manager */ public async stop() {} public async getPrerenderResultForUrl(urlArg: string): Promise { const done = plugins.smartpromise.defer(); const prerenderResult = await PrerenderResult.getPrerenderResultForUrl(this, urlArg).catch( () => { done.resolve(`Cannot render ${urlArg} due to internal error.`); return null; } ); done.resolve(prerenderResult.renderResultString); return done.promise; } /** * prerenders a sitemap */ public async prerenderDomain(domainArg: string) { logger.log('info', `prerendering domain: ${domainArg}`); await this.getPrerenderResultForUrl(`https://${domainArg}/`).catch((err) => { logger.log('error', `failed to prerender ${domainArg}`); }); await this.getPrerenderResultForUrl(`https://${domainArg}`).catch((err) => { logger.log('error', `failed to prerender ${domainArg}`); }); const robotsTxt = await this.smartrobotsInstance .parseRobotsTxtFromUrl(`https://${domainArg}/robots.txt`) .catch((err) => { logger.log('warn', `no robots for ${domainArg}`); }); if (!robotsTxt) { return; } if (robotsTxt.sitemaps.length === 0) { logger.log('warn', `robot-txt for ${domainArg} does bot sepcify any sitemaps`); } for (const sitemapUrl of robotsTxt.sitemaps) { await this.prerenderSitemap(sitemapUrl); } } public async prerenderSitemap(sitemapUrlArg: string) { logger.log('info', `prerendering sitemap: ${sitemapUrlArg}`); const parsedSitemap = await this.smartsitemapInstance.parseSitemapUrl(sitemapUrlArg); if (!parsedSitemap.urlset?.url) { return; } if (!(parsedSitemap.urlset.url instanceof Array)) { await this.getPrerenderResultForUrl(parsedSitemap.urlset.url.loc); } else { for (const url of parsedSitemap.urlset.url) { if (!url?.loc) { continue; } await this.getPrerenderResultForUrl(url.loc); } } } public async cleanPrerenderResults() { const allPrerenderResults = await PrerenderResult.getInstances({}); for (const prerenderResult of allPrerenderResults) { const extendedDate = plugins.smarttime.ExtendedDate.fromMillis(prerenderResult.timestamp); const stillValid = extendedDate.lessTimePassedToNow({ hours: 24 }); if (!stillValid) { logger.log( 'warn', `deleted prerender result for ${prerenderResult.url} since it is older than 24 hours` ); await prerenderResult.delete(); } } } }