stylex icon indicating copy to clipboard operation
stylex copied to clipboard

fix: more efficient dynamic styles

Open nmn opened this issue 1 year ago • 1 comments

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.

nmn avatar Oct 03 '24 05:10 nmn

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

github-actions[bot] avatar Oct 03 '24 05:10 github-actions[bot]