perf(cms): batch layout bootstrap, sparse fieldsets, depth caps
Deploy / verify (push) Successful in 40s
Deploy / deploy (push) Successful in 1m16s

Adopt RustyCMS' new resolve semantics (_depth, _fields,
POST /_batch) where they pay off:

- +layout.server.ts: 4 sequential GETs (navHeader, navSocial,
  footer, page_config) collapsed into one batchFetch() call.
  Legacy "default" page_config slug stays as fallback Single-
  Batch only when the canonical slug is missing.
- New getPageStubs() / getPostStubs() use _fields= so the
  Slug→Label/Slug→URL maps don't pull body/rows. Typically
  10-50× smaller payload, eligible for the same TTL cache.
- loadPostsList() now requests posts with _depth=2 and a
  sparse fieldset that keeps card-level fields plus
  postImage.* and postTag.{name,icon,color,_slug}. Body
  Markdown stays out of the listing entirely.
- Page + post detail routes set _depth=3 as a cycle/blast-radius
  cap (page → block → image → img reaches in three levels).
- cms.ts: ContentGetOptions gains depth/fields, getPageBySlug /
  getPostBySlug / getPosts thread them through (cache key
  extended). New batchFetch() / batchData<T>() helpers.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-04-30 22:00:10 +02:00
parent 35f7aa8f90
commit 3bc7273e71
5 changed files with 260 additions and 38 deletions
+24 -1
View File
@@ -255,8 +255,31 @@ export async function loadPostsList(opts: {
let cmsError: string | null = null;
try {
// Sparse fieldset für die Listen-Ansicht: Body/Rows brauchen wir hier
// nicht, nur Karten-Felder + image + tag-Metadaten. _depth=2 reicht
// (post → postImage → img-Sidecar; post → postTag → name/icon/color).
[posts, tags] = await Promise.all([
getPosts({ resolve: ["postImage"] }),
getPosts({
resolve: ["postImage", "postTag"],
depth: 2,
fields: [
"_slug",
"slug",
"headline",
"linkName",
"subheadline",
"excerpt",
"created",
"isEvent",
"eventDate",
"hideFromListing",
"postImage.*",
"postTag.name",
"postTag.icon",
"postTag.color",
"postTag._slug",
],
}),
getTags(),
]);
posts = filterHiddenPosts(sortPostsByDate(posts));