UNPKG

utquidem

Version:

The meta-framework suite designed from scratch for frontend-focused modern web development.

74 lines (60 loc) 2.03 kB
import { ModernServerContext } from '../../context'; import { RenderFunction, SSRServerContext } from '../type'; import { ERROR_DIGEST } from '../../../constants'; import { createCache } from './spr'; import { namespaceHash, withCoalescedInvoke } from './util'; import { CacheContext } from './type'; export default (renderFn: RenderFunction, ctx: ModernServerContext) => { const sprCache = createCache(); const doRender: RenderFunction = async (context: SSRServerContext) => { const cacheContext: CacheContext = { entry: context.entryName, ...context.request, }; const cacheFile = await sprCache.get(cacheContext); // no cache, render sync if (!cacheFile) { const html = await renderFn(context); const { cacheConfig } = context; if (html && cacheConfig) { await sprCache.set(cacheContext, html, cacheConfig); } return html; } const cacheHash = cacheFile?.hash; // completely expired if (cacheFile.isGarbage) { const html = await renderFn(context); const { cacheConfig } = context; if (html && cacheConfig) { await sprCache.set(cacheContext, html, cacheConfig); } return html; } else if (cacheFile.isStale) { // if file is stale, request async const render = withCoalescedInvoke(() => renderFn(context)).bind( null, namespaceHash('render', cacheFile.hash), [], ); render() .then(res => { if (res.value && res.isOrigin) { const { cacheConfig } = context; if (cacheConfig) { sprCache.set(cacheContext, res.value, cacheConfig); } else { sprCache.del(cacheContext, cacheHash); } } }) .catch(e => { sprCache.del(cacheContext, cacheHash); ctx.error(ERROR_DIGEST.ERENDER, e); }); } ctx.res.setHeader('x-modern-spr', '1'); return cacheFile.content as string; }; return doRender; };