perf: improve AutoFrame style mirroring performance and fix deduplication#1658
Open
richardszegh wants to merge 4 commits into
Open
perf: improve AutoFrame style mirroring performance and fix deduplication#1658richardszegh wants to merge 4 commits into
richardszegh wants to merge 4 commits into
Conversation
added 4 commits
May 5, 2026 11:48
…ver in AutoFrame - Replace object-hash with a lightweight djb2 hash function to avoid O(n) serialisation of large CSS strings on every style node mutation - Key style elements by href (link) or innerHTML hash (style) instead of full outerHTML, enabling early deduplication before any DOM cloning - Batch MutationObserver callbacks via a single deferred flush to prevent per-node main-thread tasks during bulk style injection from federated modules - Deduplicate style nodes during initial collection to skip duplicate PandaCSS atomic class blocks injected by multiple federated modules - Fix removeEl not splicing the elements array, causing unbounded growth
No longer used after replacing with inline djb2 hash in AutoFrame.
Two <style> tags with identical CSS but different attributes (e.g. nonce) would previously be incorrectly deduplicated. Include attributes in the hash key to restore full correctness while keeping the fast djb2 approach.
|
Someone is attempting to deploy a commit to the Puck Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1659
Disclaimer
Since I am pretty new to Puck's source code, I used a fair bit of AI help with the code. Any constructive feedback is welcome.
Our problem
In our use case, we are loading Webpack federated modules (micro-frontends) as Puck blocks. The fed. mods. are styled via PandaCSS.
Puck is using an iframe to render the drop zones/slots in the editor by default. Since iframes can't inherit any styles from the parent window Puck uses a MutationObserver to mirror every style tag from the parent into the iframe. This in combination with all the duplicated styles created by Panda CSS from our fedmods results in a ~30-45s long task blocking the main thread.
With these changes, we are no longer experiencing the issue. Drag'n'dropping blocks is now responsive, and does not block the main thread.
Description
AutoFrame'sCopyHostStylescomponent was usingobject-hashto hash the fullouterHTMLof each style node for deduplication. This is O(n) on the CSS string length and was causing significant main thread blocking when a large number of style nodes were present in the parent document.Additionally, the
MutationObservercallback was firing one independent deferred task per added/removed node, meaning a burst of style injections would queue many separate tasks rather than being handled in a single pass. There was also a bug whereremoveEldeleted the hash entry but never spliced theelementsarray, causing stale entries to accumulate indefinitely.Changes made
object-hashwith an inline djb2 hash function.<link>elements are keyed byhref,<style>elements by theirinnerHTMLhash plus serialised attributes. This avoids full node serialisation while maintaining correctness for cases where two<style>tags share identical CSS but differ in attributesmirrorEl()is called, so duplicate nodes are rejected without any DOM cloning.MutationObservercallbacks are batched: added/removed nodes are collected into pending arrays and flushed in a single deferred pass, preventing bursts of style injections from queuing one main-thread task per node.removeElto splice theelementsarray after removal, preventing stale entries that could causelookupElto return incorrect results for re-added nodes and unbounded array growth over the lifetime of the observer.object-hashas a dependency.How to test
iframeenabled (default).<style>tags into the parent document (e.g. via a CSS-in-JS library or atomic CSS framework).