@czap/worker
v0.10.0
Published
Move LiteShip's heavy work off the main thread: compositor and render workers plus a lock-free ring buffer that stream state and frames without janking the UI.
Downloads
472
Maintainers
Readme
@czap/worker
Evaluates boundary states in a Web Worker so the main thread never blocks on them.
You usually don't install this directly — it arrives as a dependency of
@czap/astro, whoseclient:workerdirective routes through it. Install that instead unless you are hosting an off-thread evaluator in your own (non-Astro) runtime.
Install
pnpm add @czap/astro # brings @czap/worker with it
# direct use: pnpm add @czap/worker @czap/coreWorkers are spawned from inline Blob URLs — no separate worker entry file, no bundler configuration. Only the SPSCRing shared-memory channel needs the page served with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp; without those headers new SharedArrayBuffer(...) throws. Everything below works without them.
30 seconds
import { Boundary, StateName } from '@czap/core';
import { CompositorWorker } from '@czap/worker';
// A boundary names the thresholds where one state becomes the next.
const layout = Boundary.make({
input: 'viewport.width',
at: [
[0, 'compact'],
[768, 'wide'],
],
});
const compositor = CompositorWorker.create();
compositor.addQuantizer('layout', {
id: layout.id,
states: layout.states.map((s) => StateName(s)),
thresholds: layout.thresholds,
});
compositor.onState((state) => {
console.log(state.discrete['layout']);
});
compositor.evaluate('layout', window.innerWidth);
compositor.requestCompute();Logs compact (below 768px) or wide — selected inside the worker, delivered back as a state snapshot. Call compositor.dispose() when finished.
Where it sits
A runtime layer one step below the host integrations: @czap/astro delegates its worker directive here rather than carrying its own worker protocol. Its only dependency is @czap/core, for boundary definitions and the shared state-snapshot contracts. It also ships SPSCRing (a lock-free shared-memory ring for streaming values out of a worker without blocking either side), RenderWorker for OffscreenCanvas rendering, and WorkerHost, a typed lifecycle wrapper around Worker. See the
package surfaces map
for the full layout.
If it does nothing
onState callbacks only fire after a compute round: if you evaluate(...) and never see a snapshot, you likely skipped requestCompute(). Pass a real Boundary.make(...).id to addQuantizer — the id is a content address (a hash of the definition), and downstream caching keys on it.
Authored-motion adapter (minimal)
motionSampleMessage(plan, t) is the worker's deliberately thin authored-motion adapter (#130): it runs the ONE shared kernel (@czap/core's sampleProgram, via the re-exported sampleProgramUniforms) off the main thread and returns a structured-clone-safe { type: 'motion-sample', css, wgsl } envelope. The host relays css/wgsl onto a bound element with dispatchCzapEvent(el, 'czap:uniform-update', …) — the SAME channel the main-thread floor already dispatches. There is no new compositor, render loop, or protocol; the sample envelope is kept out of the FromWorkerMessage union on purpose. A differential oracle proves the worker leg renders identically to every other target (ADR-0040).
Docs
- Getting started
- Hosting guide — the COOP/COEP headers per host
- Glossary — the vocabulary used above
- API reference — generated from source
Part of LiteShip — powered by the CZAP engine (Content-Zoned Adaptive Projection), distributed as @czap/* packages.
