descartes
descartes copied to clipboard
Improve Performance
This is currently the achilles heel in using this library in a production environment. CSS (and the Less, and Sass that can generate it) get all the advantages of being optimized for the browser. Using just JavaScript here means Descartes can't exploit any of those optimizations: how can we improve the performance here? Here are a few ideas and considerations:
- Generate a stylesheet. Descartes could generate CSS just like other preprocessors so that basic styles can be cached, served, and rendered. The major issue is making sure that Descartes could accurately do so because of dynamic values: since it uses inline styling and actually does style calculation at the node level, it's more specific than traditional CSS would be.
- Fine tune the code. This should happen anyways, but I have a comparatively naive understanding of JavaScript performance where others in the OS community could really contribute. The library is highly recursive, requires a lot of O(n) run throughs multiple times, and doesn't take full advantage of some of JavaScript's concurrency or caching capability. The more ideas, the better.
- Eat the cost. Maybe I'm overthinking this? What is really the cost of speed here? Is the flexibility provided by the library to do event-based, highly context-based, and largely cascade free styling worth the cost of performance? In Less and Sass (which also have similar JS libraries that compute style at load time) the cost is not justified because it's mainly used for debugging or development agility, but they do not provide many of the features that Descartes does with DOM-based styling, better computation, and dynamic values. Is there enough in Descartes to tip the scale?
Want to hear people's thoughts.
In my opinion, generating a stylesheet would undermine one of the main values of using Descartes, which is having dynamic styles directly accessible by Javascript after the page has been rendered.
That said, generating the CSS could be an optional configuration for those who want it. Maybe having a cached stylesheet and the JS styles overwrite them once they're loaded? Might affect overall performance, but still have faster initial loading.
@dfosco I think you're spot on, especially with your second point. I think generating a stylesheet and having dynamic styles post-render are not mutually exclusive, precisely because Descartes uses inline styles and would overwrite anything declared by the stylesheet. The stylesheet in this scenario would be relegated to serving a caching and backup function: it would render at least the majority of the styles needed to get the (perceived) performance, then the actual dynamism of the library would kick in as it currently does.
@JonHMChan are you saying that Descartes would split the styles? Generate the base css which is not dynamic and have js part have only the dynamic styles. That sounds like the fastest option.
@krivinarius yes, that's exactly what I'm suggesting. I think having the base styles that are not dynamic (without using a function) would be generated and used for the initial load.
@krivinarius you may be interested to see that https://github.com/JonHMChan/descartes/blob/master/src/descartes.js#L441 has been implemented to generate the base CSS, still no JS generated since I think I may refactor how event listeners are declared to make it a bit easier to bind and more performant overall.