Lazy subsystems
Fabric’s size is a build outcome, not just lean code. Three mechanisms decide what a given scene ships, in order of effect.
1. Import, and the dynamic-import seams
Section titled “1. Import, and the dynamic-import seams”The largest mechanism is ordinary tree-shaking. The main entry exports only
Camera, Scene, View, Text and Mesh as named, side-effect-free
exports; shapes, modifiers and composers sit on direct import paths. Anything
not imported is absent.
On top of that, each subsystem initialises behind a dynamic import(), so it
becomes its own chunk that is fetched only on first use:
| Subsystem | Pulled in by |
|---|---|
| SDF engine, and the grid and SDF shaders | the first shape mounting |
| Mesh engine and the glTF loader | a <Mesh> |
| Text engine | a <Text> |
| Stats overlay | stats |
| Axes | showAxes |
| Point-cloud loader | geometryUrl |
| Background mips | glass, a <Mesh>, or the reflection and refraction flags |
| Gizmo | a <Rig> |
| Blit | a drag-resize (pre-warmed at boot) |
The particle shaders are the exception — they are statically imported because boot creates the particle buffers, so they land in the eager chunk whether or not a particle component mounts. That is not dead code.
2. Region strips
Section titled “2. Region strips”A build plugin removes marked regions from fabric’s source when the app’s own
source never turns the feature on. It scans your source files, .phaze files
included and comments removed, for fingerprints rather than tracking imports,
and scans again when you edit one in dev. The strip runs on the source, before
vite-plugin-glsl resolves #include lines and minifies, so dev renders the
shader a build ships.
SDF_TYPE— one per primitive: its#include, its dispatch case in the SDF shader and its envelope case in the grid shader.[2d]is the whole 2D block.SHADER— a material branch, in bothfsandfs_fast.MODIFIER— a modifier branch in the distance function.GLASS_FEATURE— glass is not one feature but fifteen. Silhouette, sheen, refraction, slab refraction, reflection, metalness, iridescence, grain, distortion, clearcoat, chromatic aberration, attenuation, anisotropy, gloss and bicubic are each their own region, stripped independently.MESH_FEATURE— mesh glass, roughness, phong.RIG_FEATURE— the drag rig, down to its type definitions.COND_FEATURE— removes theimport()site itself, so the chunk is never emitted at all.
3. What the detection actually looks for
Section titled “3. What the detection actually looks for”The conditional strips are driven by regular expressions over your source, and
they are deliberately conservative: anything but a literal false counts as
on.
stats={false} // strippedstats // keptstats={showStats} // kept — not a literal falseThe same applies to showAxes and to enableReflection / enableRefraction.
geometryUrl is kept whenever it is mentioned at all. Glass detection keys on
shader: 'glass' and on the presence of a <Mesh tag.
Primitives and modifiers key on their JSX tag: <Box followed by a space, /
or >, so <Box does not keep BoxFrame, and <Twist for the twist branch.
The number behind a shape’s tag comes from the type: N, line in its own
component. A material branch keys on shader: 'phong' and the like. With no
shape tag anywhere nothing is stripped, and any 2D shape keeps all three 2D
primitives.
If a feature is being stripped that you need — because you enable it in a way
the scan cannot see — pin it by name in the plugin’s keep list.
The chunk pass is off
Section titled “The chunk pass is off”The plugin’s older approach cut distance functions out of the bundled chunk by
counting braces. It over-stripped under multi-environment builds and cannot
match minified text, so consumers run regionsOnly: true and it never runs.
The SDF_TYPE, SHADER and MODIFIER regions do the same job on the source.