Add build output manifest for static caching - #262
Conversation
Coverage Report for CI Build 27524398777Coverage increased (+0.3%) to 92.204%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
No dependency changes detected. Learn more about Socket for GitHub. 👍 No dependency changes detected in pull request |
31311d7 to
620a4bcComparee8c79b8 to
f665681Comparea3079c4 to
260af7aCompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
0fe8310 to
714e90dCompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
41f1f70 to
82e1fb4Compare| @@ -0,0 +1,22 @@ | |||
| { | |||
| "extends": "@voxpelli/tsconfig/node20.json", | |||
| "compilerOptions": { | |||
There was a problem hiding this comment.
Can we use the tsconfig at the root of the project rather than a dedicated shared example config?
| /** | ||
| * @param {unknown} vars | ||
| */ | ||
| function extractManifestRole (vars) { |
| }) | ||
| result.report.pages.push(buildResult) | ||
| result.report.outputs.push(...outputRecords) |
There was a problem hiding this comment.
Why did this change to a spread is that nessisary.
| }) | ||
| result.report.templates.push(buildResult) | ||
| result.report.outputs.push(...outputRecords) |
| * @template [V=string] V - The return type of the layout function (defaults to string) | ||
| * @param {string} layoutPath - The string path to the layout ESM module. | ||
| * @returns {Promise<InternalLayoutFunction<T, U, V>>} The resolved layout exported as default from the module. | ||
| * @returns {Promise<{ render: InternalLayoutFunction<T, U, V>, vars: object }>} The resolved layout render function and optional vars exported from the module. |
There was a problem hiding this comment.
Should we use something tightrr than object.
Summary
This adds an unstable-preview Domstack manifest pipeline for static caching and first-class site service-worker builds.
The manifest pipeline produces a normalized, revisioned view of build outputs for manifest hooks and optional public JSON output.
The main service-worker integration point is
hooks.manifestBuilt, where applications can derive cache policy from the finalized manifest and inject it into the final/service-worker.jsbundle withcontext.defineServiceWorkerConstant().Public
domstack-manifest.jsonwriting is opt-in.Apps that only need the manifest for service-worker policy can consume it through the hook without shipping a runtime manifest file.
Warning
The domstack manifest,
domstack-manifest.settings.*, first-classservice-worker.*entries, manifest hooks, generated browserprocess.env.DOMSTACK_*defines, and service-worker define injection are preview APIs.Their names, option shapes, manifest schema, generated output, and runtime semantics may change outside of a major version while the API is validated with real PWA use cases.
Consumers should pin
@domstack/staticto an exact version before relying on this contract.Goals
The goal is to let a domstack app build a fully static client and derive cache policy from a finalized, revisioned list of emitted files.
Domstack provides build facts and service-worker build plumbing.
The application still owns service-worker registration, update UX, route filtering, offline behavior, runtime caching decisions, and cache policy.
What Changed
results.domstackManifestfrom one-shot programmatic builds when a manifest consumer exists.domstack-manifest.jsonwriting opt-in with--domstackManifest,domstackManifest: true, or{ write: true }.report.outputsrecords.$schemaURL.domstack-manifest.settings.{js,mjs,cjs,ts,mts,cts}for manifest filtering, manifest vars, root policy, and manifest lifecycle hooks.hooks.manifestBuiltwithcontext.manifest,context.writeFile(), andcontext.defineServiceWorkerConstant().service-worker.{js,mjs,cjs,ts,mts,cts}anywhere undersrcbuilds to stable root/service-worker.js./service-worker.jswithout a circular hash dependency.domstack --servefor one-shot build plus static serving, which is useful for service-worker and PWA lifecycle testing..npmignorewith apackage.json#filesallowlist.New Preview APIs
Build Results
Programmatic one-shot builds return
results.domstackManifestwhen a manifest consumer exists.A manifest consumer is either explicit
domstackManifestconfiguration or adomstack-manifest.settings.*file.Watch mode does not return a domstack manifest.
CLI Options
--domstackManifestwrites the standarddomstack-manifest.jsonfile.--serveruns a one-shot build and serves the destination directory without watch mode or live reload snippets.Use
--servefor testing service-worker cache lifecycle behavior against stable build bytes.There is intentionally no custom manifest filename CLI shortcut.
Custom public manifest-like files should be written from a
manifestBuilthook withcontext.writeFile().Programmatic Options
Supported shape:
Use
domstackManifest: truewhen you only want to write the standard publicdomstack-manifest.jsonfile.Use the object form when you need
exclude,manifestVars,policy, orhooks.Add
write: trueto the object form only when you also want Domstack to writedomstack-manifest.json.Leaving
domstackManifestunset skips the manifest pipeline unless adomstack-manifest.settings.*file exists.A settings file enables the pipeline, returns
results.domstackManifest, and runs manifest hooks, but it does not write a public JSON file unless writing is explicitly enabled.domstack-manifest.settings.*Apps can configure the generated manifest from a dedicated settings file anywhere under
src:The default export can be an object, a sync function, or an async function returning an object.
domstackManifest.excludefrom programmatic options anddomstack-manifest.settings.*excludevalues are combined.Exclude patterns are checked against both
entry.urlandentry.outputRelname.Excludes run before
includeEntry(entry).The
includeEntry(entry)hook receives the public manifest entry shape, not local filesystem paths.Manifest Built Hooks
hooks.manifestBuiltruns after the manifest is finalized and before the final service-worker bundle is emitted.defineServiceWorkerConstant()serializesvaluewithJSON.stringify()and passes it to esbuild'sdefineoption for the final service-worker build.Use it for precomputed service-worker policy, such as a vanilla precache list or a Workbox-shaped
precacheManifest, when you do not want a runtime fetch or generated global script.writeFile()writes generated artifacts underdest.Use it for custom public integration data when a runtime file is intentionally desired.
Service Worker Support
Domstack reserves one site service-worker source filename:
The source may live anywhere under
src, but only one is allowed.Multiple matches fail with
DOM_STACK_ERROR_DUPLICATE_SERVICE_WORKER.The service worker is bundled through esbuild and emitted with a stable root output path:
The final service-worker build receives manifest hook defines and
process.env.DOMSTACK_MANIFEST_VERSION.Domstack does not inject registration into the default layout.
Registration timing, update prompts, local-development opt-outs, poisoned-cache recovery, and offline route behavior remain application policy.
Browser Defines
process.env.DOMSTACK_MANIFEST_URL/domstack-manifest.jsonprocess.env.DOMSTACK_MANIFEST_VERSION/service-worker.js;""in other bundlesprocess.env.DOMSTACK_MANIFEST_ENABLED"true"for one-shot builds with an enabled manifest pipeline,"false"when disabled or in watch modeprocess.env.DOMSTACK_SERVICE_WORKER_URL/service-worker.js, or""when no service worker is presentprocess.env.DOMSTACK_SERVICE_WORKER_SCOPE/, or""when no service worker is presentCompatibility Notes
domstack-manifest.jsononly when--domstackManifestis set.domstack-manifest.jsononly withdomstackManifest: trueor{ write: true }.entries.manifest.versioncan be embedded into/service-worker.jswithout a circular hash dependency.copyis the output kind for files copied by the generic copy step.{ url, revision }precache shape fromcontext.manifestinside a manifest hook.Testing
npm testnpm run test:tscnpm run test:neostandardnode --test lib/identify-pages.test.js test-cases/general-features/index.test.js test-cases/type-exports/index.test.ts test-cases/watch/index.test.js test-cases/template-output-escape/index.test.jsgit diff --check