Skip to content

Document global.data.js caveats: vars getter, error handling, and raw content #228

@bcomnes

Description

@bcomnes

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:

  1. That .vars is a computed getter that performs a fresh 4-way merge on every access
  2. That .vars can throw if a page module has errors (syntax errors, missing dependencies)
  3. That .vars.content for markdown pages is raw markdown, not rendered HTML
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationdx

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions