docs / Compiler
Static Code Generation
How the client codegen distinguishes fully-static subtrees from reactive ones, and how hydrate-mode markers work.
The client codegen distinguishes fully-static subtrees from reactive ones at compile time. Static subtrees are constructed once and never touched by effects; reactive subtrees get per-cell DOM update wiring.
isStaticIR
- `isStaticIR(body)` returns true only when every node is a StaticNode or TextNode and no attribute binding (including on* handlers) is dynamic.
- A component whose whole body is static gets no effect wiring — its DOM is built once, synchronously.
- A component with a `<style>` block is never static.
- A MapRegion counts as static only when both its template and alternate are static.
Hydrate-mode markers
subtreeNeedsJS
subtreeNeedsJS = __vskHydrate && (forceClaim || !isStaticIR(node.children))
- Static subtrees: no marker, no client-side reconstruction — the server HTML is claimed as-is.
- Reactive subtrees: a `<!--vsk-->` marker tells the client hydrator where to attach effects and per-cell update code.
- forceClaim forces a claim marker even for a static-looking subtree (e.g. event delegation).
Static props
Module-level `export const props = { ... }` static data is hoisted into IRRoot.staticProps and re-emitted once, shared by server and client outputs instead of being re-evaluated per component.