Currently, hot module reloading pages that use Emotion with React is about 8x slower than using CSSStyleSheet.replaceSync to update styles.
Here are two Chrome profiles where the same CSS is updated on disk 1024 times, sleeping for 32ms between each update. In the first case, it's a <Global> React component, and in the second case, it's a <link> tag being hot reloaded
with-emotion-react.json.gz - this one is using Emotion and the React Component is being re-imported each time. Note the difference in time spent on Rendering between the two profiles.
Detect if CSSStyleSheet.replaceSync is supported in the current browser and use that to update the existing stylesheet (rather than creating a new one). This would work for both development and production (in production for dynamic styles).
Drawbacks:
This API is only available in Chromium browsers. Multiple "backends" for updating styles introduces complexity
@import is not supported with CSSStyleSheet.replaceSync
Alternative solutions
Additional context
replaceSync has some cost, but it's not so bad:
Versus:
Incase opening the profiles are a pain, here are screenshots.
Hey look, someone finally did the research and found the 5-8x performance improvement that was hiding in this article...who knew? 😜
Potential 5x perf improvement for stylesheet updates by switching to `CSSStyleSheet.replaceSync` #2501
The problem
Currently, hot module reloading pages that use Emotion with React is about 8x slower than using
CSSStyleSheet.replaceSync
to update styles.Here are two Chrome profiles where the same CSS is updated on disk 1024 times, sleeping for 32ms between each update. In the first case, it's a
<Global>
React component, and in the second case, it's a<link>
tag being hot reloadedwith-emotion-react.json.gz - this one is using Emotion and the React Component is being re-imported each time. Note the difference in time spent on Rendering between the two profiles.
with-replaceSync.json.gz - this one is using
CSSStyleSheet.replaceSync
This is the CSS:
This is the React component using Emotion:
Proposed solution
Detect if
CSSStyleSheet.replaceSync
is supported in the current browser and use that to update the existing stylesheet (rather than creating a new one). This would work for both development and production (in production for dynamic styles).Drawbacks:
@import
is not supported withCSSStyleSheet.replaceSync
Alternative solutions
Additional context
replaceSync
has some cost, but it's not so bad:Versus:
Incase opening the profiles are a pain, here are screenshots.
Emotion:
replaceSync: