Performance
The layout engine compiles descriptor trees once, reuses text metrics, and caches subtree layouts by width. Repeated relayouts are just arithmetic.
When you call computeLayout(descriptor, width), the engine does two things:
Compiles the descriptor tree — prepares text metrics, resolves padding/margin, and builds reusable node metadata. This is the expensive part.
Reuses the compiled tree and subtree caches keyed by width. Only box-model arithmetic runs — no text re-measurement, no tree re-walking.
This happens automatically. If you pass the same descriptor object twice, the second call reuses the compiled state from the first.
The simplest API. The engine auto-compiles on the first call and caches for subsequent ones.
import { computeLayout } from "boneyard-js"
const mobile = computeLayout(descriptor, 375) // cold: compiles + layouts
const desktop = computeLayout(descriptor, 1280) // warm: reuses compiledIf you only use computeLayout, you don't need to change anything. You already get the caching benefit.
Use compileDescriptor() when you want to control exactly when the cold step happens.
import { compileDescriptor, computeLayout } from "boneyard-js"
const compiled = compileDescriptor(descriptor)
const mobile = computeLayout(compiled, 375) // hot
const tablet = computeLayout(compiled, 768) // hot
const desktop = computeLayout(compiled, 1280) // hotThis is useful for:
- SSR rendering at multiple breakpoints
- Descriptor registries loaded once at startup
- Animation loops or responsive tools that relayout often
- Benchmarking cold vs warm cost separately
If you mutate a descriptor object in place, the engine detects the change and rebuilds the compiled state automatically on the next layout call.
descriptor.children[0].text = "Updated title"
// Automatically detects the mutation and recompiles
const result = computeLayout(descriptor, 375)You can also force a rebuild immediately with invalidateDescriptor():
import { invalidateDescriptor } from "boneyard-js"
invalidateDescriptor(descriptor) // clears cached compiled stateMeasured with the built-in benchmark runner (pnpm --dir packages/boneyard benchmark).
| Case | Cold | Warm | Compiled | Speedup |
|---|---|---|---|---|
| text-leaf | 0.041 ms | 0.0004 ms | 0.0004 ms | ~105x |
| dashboard-card | 0.096 ms | 0.006 ms | 0.006 ms | ~16x |
Cold = brand new descriptor each call. Warm/compiled = same object, cache populated. Run your own benchmarks with pnpm --dir packages/boneyard benchmark.