Closed necolas closed 6 years ago
I assume you're more interested in dynamic changes with navigation like https://github.com/blakeembrey/react-free-style? This library doesn't really handle any replacing on style dynamically, but I even with the React version I haven't done any in-depth testing. Do you have any ideas on how we could put together a decent test?
I think replacing <style>
is not a most often operation.
Changing between preset states is much more often behaviour, that dynamic style generation. And changing preset state wil be very fast in FreeStyle — just change class in component.
Theoretically free-style
is as fast as using plain CSS or inline styles. Perhaps even faster with the smaller selector footprint. All stringification happens outside the render loop and the only activity happening for render changes is either the class name, or, potentially (given the project, e.g. react-free-style
), <style />
changes when a style is added or removed entirely. The CSS strings themselves are always cached and not generated dynamically, unless you create the style objects inside render.
Given that, it would be still be really cool to have a realistic benchmark. Perhaps even on page with a timer with simplistic navigation.
There could be some compelling reasons to improve the runtime performance of altering the stylesheets generated by free-style.
I'm currently experimenting (very unscientifically) with dynamically-generated styles in a way that feels more like Radium from the developer point of view.
I find Radium's interface appealing, but their implementation leads to a number of problems that FreeStyle addresses elegantly with ordinary CSS.
Here's a repo with an experimental Radium-like interface to react-free-style: https://github.com/namuol/react-dynamic-styles-experiment
Of course, this doesn't scale as it is implemented right now, since I'm effectively re-generating the entire page's stylesheet any time a new style appears.
However, this approach has some noteworthy benefits:
className
), styles are just plain objects everywhere.@media
, :hover
, etc.I find this interface compelling, and believe the performance problems are addressable, so I might attempt to hack together something designed from the ground up to be more dynamic and see if I can get the performance to be acceptable with very large (1000+ rule) stylesheets.
Thoughts?
I ended up experimenting with a way of hijacking use of the style
prop and limiting the total size of the CSS to the number of unique declarations: https://github.com/necolas/react-web-sdk. Build-time extraction would be better, but the interface is there.
@namuol @necolas Thanks for the links, I'm definitely going to spend some time reviewing all the ideas being presented. I like the merging of common styles down to the rule level - do you have any statistics on style size output?
I went for the middle ground in the rewrite at #6, where all styles that are duplicates are merged (at any level - e.g. @
-rules, root, etc.) - but one unique selector is generated to reference them all and styles now have multiple selectors. Outputting multiple CSS classes like you do for the different levels could be another approach which would be interesting to compare output size.
The precomputed library I am using is under 5 KB gzipped. Some stats from cssstats.com:
114 Properties 594 Unique Declarations (includes vendor prefixes) 419 Rules 433 Selectors 604 Declarations
Comparison with twitter.com (which is an extreme case):
138 Properties 2,152 Unique Declarations 3,095 Rules 4,635 Selectors 6,826 Declarations
The number of properties is very similar (bounded quantity), the number of unique declarations on twitter.com (although excessive) is far smaller than the number of rules, selectors, or declarations.
Have you done any performance profiling for the current strategy? For example, I'm curious how expensive it is to replace the whole contents of the
style
element for a large app.