-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
StyleSheet: perf characteristics #110
Comments
@vjeux shared some finding with me about how Chrome performs:
This means injecting single classes like react-native-web has been doing should perform fine in Chrome. However, inline styles appear to be very cheap in Chrome too. And they avoid potentially creating very large strings when producing the style sheet. |
This fixes several issues with 'StyleSheet' and simplifies the implementation. 1. The generated style sheet could render after an apps existing style sheets, potentially overwriting certain 'html' and 'body' styles. To fix this, the style sheet is now rendered first in the document head. 2. 'StyleSheet' didn't make it easy to render app shells on the server. The prerendered style sheet would contain classnames that didn't apply to the client-generated style sheet (in part because the class names were not generated as a hash of the declaration). When the client initialized, server-rendered parts of the page could become unstyled. To fix this 'StyleSheet' uses inline styles by default and a few predefined CSS rules where inline styles are not possible. 3. Even with the strategy of mapping declarations to unique CSS rules, very large apps can produce very large style sheets. For example, twitter.com would produce a gzipped style sheet ~30 KB. Issues related to this are also alleviated by using inline styles. 4. 'StyleSheet' didn't really work unless you rendered an app using 'AppRegistry'. To fix this, 'StyleSheet' now handles injection of the DOM style sheet. Using inline styles doesn't appear to have any serious performance problems compared to using single classes (ref #110). Fix #90 Fix #106
Actually, I'm sorry but this was a completely busted analysis. I later found out what was really happening. So, when you inject stylesheets, there's a fast path that checks every rule against the current DOM and if it matches, then flags the dom node as dirty and dirties the entire subtree. This check is very crude, if you have a rule Then, the expensive part is to re-compute the styles of all the elements that are dirty. This scales linearly with the number of dom nodes. If you end up dirtying the root element (we have a ton of top level classes on facebook.com like Also, note that you only need one rule that dirties a big tree to pay the cost for the entire stylesheet you inject. |
Ouch, that sounds much worse. Inline styles it is! |
After discussing this with @vjeux I thought of a few more things to include in a performance evaluation of inline styles vs class names.
StyleSheet
creating a large string in memoryStyleSheet
updating a single<style>
element's content (and does the browser recalc everything when you do so?)The text was updated successfully, but these errors were encountered: