Cache-bust strategy for Vanilla-Grid

This document describes the small, deterministic cache-busting strategy for the vanilla-grid component. It focuses on two modes of operation:

The strategy deliberately avoids adding or relying on globals attached to window (e.g. window.VANILLA_GRID_CACHE_BUST).

Actual identifiers: the pseudo-code below uses the generic names resolveCacheBustToken() / appendCacheToken(). The shipped implementations are per-file-prefixed: _vnGridResolveCacheBustToken / _vnGridAppendCacheToken in vanilla-grid-element.js, and _vnToolbarResolveCacheBustToken / _vnToolbarAppendCacheToken in vanilla-grid-toolbar.js. Grep for those names, not the generic ones, when tracing this behavior in the source.

Goals

Scope

Apply cache-busting to the following vanilla-grid runtime assets only:

This does NOT change bundling strategy (content-hashed filenames are still the recommended long-term approach). This covers a query-token strategy implemented inside the runtime code and resolved at build time.

Resolution algorithm (simple)

When an asset URL must be written, resolve the token as follows (priority order):

  1. If the build-time placeholder __VANILLA_COMPONENTS_VERSION__ is present and non-empty, use it as the token (string).
  2. Otherwise (development/unbuilt), use a fresh timestamp: String(Date.now()) (generated at the moment of injection).

Notes:

Helper utilities (pseudocode)

Add a tiny helper pair (can be duplicated in the two files or factored into a shared module):

// Build-time token placeholder. Build tooling will replace __VANILLA_COMPONENTS_VERSION__
// with the actual version string (e.g. '1.2.3'). When not replaced, typeof check prevents
// reference errors.
function resolveCacheBustToken() {
  if (typeof __VANILLA_COMPONENTS_VERSION__ !== 'undefined' && __VANILLA_COMPONENTS_VERSION__) {
    return String(__VANILLA_COMPONENTS_VERSION__);
  }
  // Dev fallback — generated when called so repeated calls produce fresh values.
  return String(Date.now());
}

function appendCacheToken(url, token) {
  return url + (url.indexOf('?') === -1 ? '?v=' : '&v=') + encodeURIComponent(token);
}

Implementation notes:

Where it is implemented

Each file carries its own small copy of the helpers (no shared module), so every script stays self-contained.

Build-time injection

build.js substitutes the placeholder: injectVersionPlaceholder() replaces every __VANILLA_COMPONENTS_VERSION__ with a JSON string literal of the root package.json version, and processJs() calls it before any minifier/obfuscator pass, so downstream tooling sees a plain string (and can drop the dev Date.now() branch). Unbuilt sources leave the identifier undeclared; the typeof guard falls back to Date.now().

Testing & verification

Dev (no build-time token injected)

  1. Start the app without running replacement injection.
  2. Observe that injected link.href and script src values contain a ?v=<timestamp> token (use Network panel). The timestamp should change across reloads and — for theme switches — should change when _updateThemeStylesheet runs.

Prod (build-time token injected)

  1. Run the build that replaces __VANILLA_COMPONENTS_VERSION__ with the package version (e.g. 1.2.3).
  2. Serve the dist assets and open the app. Verify that injected link.href and script src include ?v=1.2.3 and that value does not change on reload or theme switch.

Edge cases

Recommendations & trade-offs

Appendix — concise code snippet (complete)

// top of file (vanilla-grid-element.js / vanilla-grid.js)
function resolveCacheBustToken() {
  if (typeof __VANILLA_COMPONENTS_VERSION__ !== 'undefined' && __VANILLA_COMPONENTS_VERSION__) {
    return String(__VANILLA_COMPONENTS_VERSION__);
  }
  return String(Date.now());
}

function appendCacheToken(url, token) {
  return url + (url.indexOf('?') === -1 ? '?v=' : '&v=') + encodeURIComponent(token);
}

// usage examples:
// base stylesheet
link.href = appendCacheToken(_vnGridBaseUrl + 'vanilla-grid.css', resolveCacheBustToken());

// autoloader scripts (one token for the autoloader run)
const autoloaderToken = resolveCacheBustToken();
s.src = appendCacheToken(base + relSrc, autoloaderToken);

// theme switch — fresh token per switch in dev, stable in prod
link.href = appendCacheToken(href, resolveCacheBustToken());