fix: more efficient dynamic styles
More efficient dynamic styles
Dynamic Styles in StyleX are expressed as minimal arrow functions that return an arrow expression. These styles are then compiled into a function that returns a tuple of two objects — an object of static classNames and an object of inline styles that only sets some CSS variables.
The CSS variables defined as inline styles are used in the statically generated CSS as values for the properties that are to have a dynamic value.
What changed
In this PR, the biggest change is that the object of static classNames is slightly more dynamic than before. Instead of statically returning classNames for all properties, the classNames are now only returned conditionally when the dynamic value passed into the function for that particular party is not null or undefined.
What does that mean?
In short this means that after this change, if a property's dynamic value resolves to null or undefined, no className will be applied for that property at all.
This makes null dynamic values more efficient.
But also,
Previously, the inline styles would default to initial when the dynamic value was null or undefined. Now they default to undefined. This will mean that when a value is null or undefined, instead of setting a CSS variable to initial, we will simply omit it from the inline styles which has the same effect.
This is also a small efficiency improvement.
What's still missing
When a property has an object value with pseudo classes and/or media queries, where one of the sub-values is dynamic, the classNames are still applied in all cases. This is because the code makes it difficult to know exactly which className in a space-separated list of classes needs to be applied conditionally.
This behaviour is more than an efficiency problem and can actually apply undesired "default" styles for null values which is not consistent with what happens when null is used as a static value.
I will be fixing this issue next.
workflow: benchmarks/size
Comparison of minified (terser) and compressed (brotli) size results, measured in bytes. Smaller is better.
@stylexjs/[email protected] size:compare ./size-compare.js /tmp/tmp.6fF5Oo7ije /tmp/tmp.w3y4OeKKt9
| Results | Base | Patch | Ratio | |
|---|---|---|---|---|
| stylex/lib/stylex.js | ||||
| · compressed | 899 | 899 | 1.00 | |
| · minified | 3,223 | 3,223 | 1.00 | |
| stylex/lib/StyleXSheet.js | ||||
| · compressed | 1,266 | 1,266 | 1.00 | |
| · minified | 3,776 | 3,776 | 1.00 | |
| rollup-example/.build/bundle.js | ||||
| · compressed | 563,484 | 563,025 | 1.00 | - |
| · minified | 10,185,368 | 10,185,368 | 1.00 | |
| rollup-example/.build/stylex.css | ||||
| · compressed | 99,154 | 99,154 | 1.00 | |
| · minified | 745,649 | 745,649 | 1.00 |