Skip to content

perf(web): optimize cssListener for rapid stylesheet additions#209

Merged
Brentlok merged 2 commits into
uni-stack:mainfrom
ForestSpark:fix/csslistener-performance-optimization
Dec 6, 2025
Merged

perf(web): optimize cssListener for rapid stylesheet additions#209
Brentlok merged 2 commits into
uni-stack:mainfrom
ForestSpark:fix/csslistener-performance-optimization

Conversation

@ForestSpark

Copy link
Copy Markdown
Contributor

Summary

Fixes performance issues when CSS-in-JS libraries inject many stylesheets rapidly (e.g., Emotion's 2000+ style tags in dev mode).

Previously, the MutationObserver would call initialize() on every DOM mutation, reprocessing all stylesheets each time, causing O(n²) complexity. This resulted in 7+ second navigation delays in development environments.

Changes

  • Debounce initialization: Use requestIdleCallback (with setTimeout fallback) to batch rapid mutations into a single initialization call (50ms timeout)
  • Track processed stylesheets: Use WeakSet to skip already-processed stylesheets
  • Helper functions: Extract cross-platform idle callback scheduling utilities with comprehensive documentation

Performance Impact

  • Before: 2000 stylesheets × 2000 iterations = 4M operations (O(n²))
  • After: 2000 stylesheets × 1 iteration = 2K operations (O(n))
  • Result: ~99.95% reduction in operations

Testing

  • Built successfully with unbuild
  • Passes ESLint checks
  • Tested in development environment with Emotion generating 2000+ style tags

Related

Addresses the performance concerns discussed in #188

ForestSpark and others added 2 commits December 5, 2025 15:20
Fixes performance issues when CSS-in-JS libraries inject many stylesheets rapidly (e.g., Emotion's 2000+ style tags in dev mode). Previously, the MutationObserver would call initialize() on every DOM mutation, reprocessing all stylesheets each time, causing O(n²) complexity.

Changes:
- Debounce initialization with requestIdleCallback (50ms timeout, setTimeout fallback)
- Track processed stylesheets with WeakSet to avoid reprocessing
- Extract helper functions for cross-platform idle callback scheduling

This reduces operations from O(n²) to O(n), improving navigation performance significantly in development environments.

@Brentlok Brentlok left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done minor refactor to simplify things a bit. Thanks for PR 👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants