feat(sdk): CDN bundle preload mode for @contentrain/query#70
Merged
Conversation
createContentrain({ bundle: true }) fetches _bundle/{locale}.json once and
serves all content/document-index/dictionary reads from memory, collapsing
per-render fetch waterfalls into a single conditional GET. Default off —
non-breaking minor.
Key decisions:
- Bundle logic scoped to content/, documents/, meta/ paths; manifest and
models/* paths never derive a locale, avoiding spurious _bundle requests
- Existing fetch() body moved verbatim to _networkFetch(); per-path ETag
cache, 304 handling and ContentrainError semantics unchanged, so the
bundle request itself revalidates via 304 for free
- Stale primed paths evicted when a fresh bundle drops them; 404/invalid/
network error → transparent per-path fallback retried after revalidateMs
- revalidateMs: 0 supported (revalidate every fetch); non-i18n data.json
entries resolve via defaultLocale
- client.preload(locale?) for eager SSR warmup; concurrent first reads
dedupe into one inflight bundle request
Tests: 15 new cases in tests/cdn/bundle-preload.test.ts covering priming,
out-of-scope fallback, 404 retry, 304 revalidation, eviction, version
guard, data.json locale mapping, inflight dedupe, manifest guard, preload
semantics and revalidateMs: 0. Full suite: 250 passing, oxlint/tsc clean.
✅ Deploy Preview for contentrain-ai ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an opt-in bundle preload mode to the CDN transport:
createContentrain({ bundle: true })fetches_bundle/{locale}.json(one artifact containing every JSON model for the locale, produced by Studio #125) and serves all collection/singleton/dictionary/document-index reads from memory. Per-render cost drops from N content fetches + include waterfall to 1 conditional GET.Default off → non-breaking minor (6.1.1 → 6.2.0, changeset included).
Design
fetch<T>()body moved verbatim to_networkFetch<T>()— per-path ETag cache,If-None-Match/304 andContentrainErrorsemantics unchanged. The bundle request itself revalidates via 304 for free._ensureBundle(locale): inflight dedupe (concurrent first reads → one request),revalidateMsfreshness window (default 60s), stale-path eviction when a fresh bundle drops entries,missingstate on 404/invalid/version !== "1"with retry after the window.content/,documents/,meta/paths consult the bundle —_manifest.json,models/*,_media_manifest.jsonhave no locale segment and would otherwise trigger spurious_bundle/...requests. Doc bodies (bySlug()) andwithMeta()stay per-path, as speced.content/{model}/data.jsonbundle keys resolve viadefaultLocale;revalidateMs: 0means revalidate-on-every-fetch;client.preload(locale?)gives eager SSR warmup and is a network-freefalsewhen bundle mode is off._resolveIncludes, forms/conversation clients untouched — everything routes throughtransport.fetch(), so include resolution is covered automatically.Rollout
Safe to publish before Studio #125: while the CDN returns 404 for
_bundle/..., behavior is identical to per-path fetching today. Full win starts after the first bundle-producing rebuild.Testing
tests/cdn/bundle-preload.test.ts: single-GET priming, out-of-scope fallback, 404 → retry afterrevalidateMs, 304 keeps primed data, eviction of removed paths, unknown-version rejection,data.json→ defaultLocale mapping, concurrent inflight dedupe, manifest/models guard,preload()semantics (found/missing/mode-off),revalidateMs: 0.tsc --noEmitclean,pnpm build(dts) clean.docs/packages/sdk.mdgained a "Bundle Preload" section; CDN-vs-Local tables updated.🤖 Generated with Claude Code