This issue was originally identified in voxpelli/voxpelli.github.com#32
Problem
The DomStack README has a dedicated global.data.js section but several important runtime caveats are not covered. Users must discover these through source diving or trial and error:
- That
.vars is a computed getter that performs a fresh 4-way merge on every access
- That
.vars can throw if a page module has errors (syntax errors, missing dependencies)
- That
.vars.content for markdown pages is raw markdown, not rendered HTML
- That
renderInnerPage() is available in global.data.js (it runs after page initialization)
These caveats have real consequences for build reliability and performance.
What the README already covers
- Purpose, input, output, types (
GlobalDataFunction<T>, AsyncGlobalDataFunction<T>)
- A complete working example
- Variable merge order
What's missing: runtime caveats
1. page.vars is a computed getter
The .vars property performs a fresh { ...globalVars, ...globalDataVars, ...pageVars, ...builderVars } spread on every access. Cache the result when reading multiple properties:
// GOOD -- single getter invocation
const vars = page.vars;
const { title, date, lang, category } = vars;
// AVOID -- triggers a fresh 4-way merge on each access
const title = page.vars.title;
const date = page.vars.date;
For large sites with hundreds of pages, caching can noticeably reduce build time.
2. page.vars may throw
If the underlying page.vars.js module has a syntax error, missing import, or runtime exception, accessing .vars will throw. When iterating all pages, always wrap in try/catch:
const posts = pages.filter(p => {
try {
return p.vars.layout === 'article' && p.vars.date;
} catch {
return false; // Skip broken pages gracefully
}
});
3. page.vars.content is raw source, not rendered HTML
For markdown pages, vars.content is the raw markdown string. To get rendered HTML, use renderInnerPage().
4. renderInnerPage() availability
global.data.js runs after pages are initialized and renderInnerPage() is available. However, using it in global.data.js means the rendered content will be computed during the global data phase — document this clearly so users understand the build pipeline ordering.
Proposed solution
Add a "Caveats" or "Important notes" subsection to the existing global.data.js documentation covering these four points. This is a small addition to the existing documentation section — not a new section from scratch.
Source code confirmation
Vars getter (confirmed in lib/build-pages/page-data.js):
get vars () {
if (!this.#initialized) throw new Error('Initialize PageData before accessing vars')
const { globalVars, globalDataVars, pageVars, builderVars } = this
return {
...globalVars,
...globalDataVars,
...pageVars,
...builderVars,
}
}
Every .vars access creates a new spread of four objects. No caching.
Problem
The DomStack README has a dedicated
global.data.jssection but several important runtime caveats are not covered. Users must discover these through source diving or trial and error:.varsis a computed getter that performs a fresh 4-way merge on every access.varscan throw if a page module has errors (syntax errors, missing dependencies).vars.contentfor markdown pages is raw markdown, not rendered HTMLrenderInnerPage()is available inglobal.data.js(it runs after page initialization)These caveats have real consequences for build reliability and performance.
What the README already covers
GlobalDataFunction<T>,AsyncGlobalDataFunction<T>)What's missing: runtime caveats
1.
page.varsis a computed getterThe
.varsproperty performs a fresh{ ...globalVars, ...globalDataVars, ...pageVars, ...builderVars }spread on every access. Cache the result when reading multiple properties:For large sites with hundreds of pages, caching can noticeably reduce build time.
2.
page.varsmay throwIf the underlying
page.vars.jsmodule has a syntax error, missing import, or runtime exception, accessing.varswill throw. When iterating all pages, always wrap in try/catch:3.
page.vars.contentis raw source, not rendered HTMLFor markdown pages,
vars.contentis the raw markdown string. To get rendered HTML, userenderInnerPage().4.
renderInnerPage()availabilityglobal.data.jsruns after pages are initialized andrenderInnerPage()is available. However, using it inglobal.data.jsmeans the rendered content will be computed during the global data phase — document this clearly so users understand the build pipeline ordering.Proposed solution
Add a "Caveats" or "Important notes" subsection to the existing
global.data.jsdocumentation covering these four points. This is a small addition to the existing documentation section — not a new section from scratch.Source code confirmation
Vars getter (confirmed in
lib/build-pages/page-data.js):Every
.varsaccess creates a new spread of four objects. No caching.