UNPKG

astro

Version:

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

44 lines (43 loc) • 1.77 kB
import { getInstalledRenderScope } from "./scope.js"; let warnedNoScope = false; /** * Runs `fn` inside a fresh per-render collectors store and returns its value * together with a snapshot of everything recorded while it ran. * * When no render scope is installed, collection degrades to *not collecting*: * warn once per process (when a `logger` is given), run `fn` bare, and return * `metadata: undefined` ("not tracked") — never wrong attribution. * * Invariant: `fn` must not resolve until all recordable work is done — in * practice, until the response body is fully buffered inside `fn`. The * snapshot is taken by copy when `fn` resolves, so a late-arriving record (a * floating promise carrying the async context past buffering) mutates only the * abandoned store, never the returned metadata. */ export async function collectPrerenderMetadata(fn, logger, options = {}) { const scope = getInstalledRenderScope(); if (!scope) { if (logger && !warnedNoScope) { warnedNoScope = true; logger.warn("build", "A prerenderer collected metadata but no render scope is installed; " + "install one with `installRenderScope` from `astro/app` — optimized images and " + "incremental metadata will not be collected for prerendered paths."); } return { value: await fn(), metadata: undefined }; } const store = { contentEntries: new Set(), staticImages: options.staticImages === false ? undefined : [], referencedImages: new Set() }; const value = await scope.run(store, fn); return { value, metadata: { contentEntryKeys: [...store.contentEntries], staticImages: [...new Map(store.staticImages?.map((image) => [`${image.originalPath}\0${image.hash}`, image])).values()], referencedImages: [...store.referencedImages] } }; }