diff --git a/.changeset/archive-month-labels.md b/.changeset/archive-month-labels.md new file mode 100644 index 0000000000..e1989ed163 --- /dev/null +++ b/.changeset/archive-month-labels.md @@ -0,0 +1,5 @@ +--- +"emdash": patch +--- + +Reduces the CPU work needed to render the Archives widget on sites with many posts. Archive links, ordering, and post counts stay the same. diff --git a/.changeset/quiet-widgets-share.md b/.changeset/quiet-widgets-share.md new file mode 100644 index 0000000000..e7df1fb9b8 --- /dev/null +++ b/.changeset/quiet-widgets-share.md @@ -0,0 +1,5 @@ +--- +"emdash": patch +--- + +Reduces duplicate database reads when widget areas render while layout prefetch is still running on remote database adapters. diff --git a/infra/perf-monitor/probe/src/measure.ts b/infra/perf-monitor/probe/src/measure.ts index 9395fbd5b4..ed8799aa0d 100644 --- a/infra/perf-monitor/probe/src/measure.ts +++ b/infra/perf-monitor/probe/src/measure.ts @@ -101,8 +101,8 @@ async function measureTtfb(url: string): Promise<{ const response = await fetch(url, { method: "GET", headers: { + Accept: "text/html", "User-Agent": "emdash-perf-probe/1.0", - // Bust any edge cache "Cache-Control": "no-cache", }, redirect: "follow", @@ -149,7 +149,7 @@ export async function measureRoutes(req: MeasureRequest): Promise for (const route of req.routes) { const url = `${req.targetUrl}${route.path}`; - // Cold request -- add a unique query param to avoid any isolate reuse + // A distinct URL does not guarantee a fresh Worker isolate. const coldUrl = url + (url.includes("?") ? "&" : "?") + `_perf_cold=${Date.now()}`; const cold = await measureTtfb(coldUrl); diff --git a/packages/core/src/astro/prefetch.ts b/packages/core/src/astro/prefetch.ts index 88265b2993..fbfe4f00d7 100644 --- a/packages/core/src/astro/prefetch.ts +++ b/packages/core/src/astro/prefetch.ts @@ -25,14 +25,14 @@ import { getDb } from "../loader.js"; import { getMenu } from "../menus/index.js"; -import { setRequestCacheEntry } from "../request-cache.js"; +import { requestCached, setRequestCacheEntry } from "../request-cache.js"; import { getSiteSettings } from "../settings/index.js"; import { getTaxonomyDefs, getTaxonomyTerms } from "../taxonomies/index.js"; import { getWidgetAreas } from "../widgets/index.js"; /** Warm widget areas: one bulk load, primed under each per-area cache key. */ async function prefetchWidgetAreas(): Promise { - const areas = await getWidgetAreas(); + const areas = await requestCached("widget-areas", getWidgetAreas); // getWidgetArea(name) caches under `widget-area:${name}` and returns the same // WidgetArea shape getWidgetAreas yields, so priming here makes those calls hit. for (const area of areas) { diff --git a/packages/core/src/components/widgets/Archives.astro b/packages/core/src/components/widgets/Archives.astro index 4d1c3b3d6d..df244b6a1e 100644 --- a/packages/core/src/components/widgets/Archives.astro +++ b/packages/core/src/components/widgets/Archives.astro @@ -1,5 +1,5 @@ --- -import { getEmDashCollection } from "../../query.js"; +import { getPublishedDates } from "../../query.js"; import { groupEntriesByPublishedAt } from "../../widgets/archives.js"; interface Props { @@ -9,11 +9,12 @@ interface Props { const { type = "monthly", limit = 12 } = Astro.props; -const { entries: posts } = await getEmDashCollection("posts", { - orderBy: { published_at: "desc" }, -}); +const { dates } = await getPublishedDates("posts"); -const archiveList = groupEntriesByPublishedAt(posts, { type, limit }); +const archiveList = groupEntriesByPublishedAt( + dates.map((publishedAt) => ({ data: { publishedAt } })), + { type, limit }, +); ---