- From: Nick Coury <notifications@github.com>
- Date: Tue, 10 Oct 2023 09:22:34 -0700
- To: WICG/webcomponents <webcomponents@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <WICG/webcomponents/issues/809/1755787377@github.com>
+1 to the general idea here. We described a similar need in https://github.com/whatwg/dom/issues/1116 and are much further along in development of a solution (and subsequent pains). We are using a detached document (relevant [HTTP 203](https://youtu.be/LLRig4s1_yA?t=1283)) to progressively enhance a cross-document MPA experience into a single-document SPA experience similar to something like [Turbolinks](https://github.com/turbolinks/turbolinks) or [MarkoJs](https://markojs.com/) which uses [writeable-dom](https://github.com/marko-js/writable-dom). We selectively update the page instead of replacing the entire document, using annotations to identify which elements to replace from the old page to the new page. This approach is providing significant benefits over a custom SPA streaming and chunking protocol on the server+client, and will allow us to drastically simplify parts of our architecture while still providing a modern web experience. At the same time, it has presented two main challenges that have required workarounds that this proposal would help: 1. Inline scripts need to be manually executed when moved/streamed from the detached document to the visible document. 2. We use animations on certain elements when moving them to the visible document, either using the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) or WAAPI animations. We use a MutationObserver on the detached document to watch for annotated elements that need to replace their counterpart in the visible document. We move the node as soon as we get the opening tag, which can decrease the time for users to see content especially on slow connections when the content is large. ### Inline scripts The issue here is that we only get notified on the opening tag of the script, and don't know if the script is complete. If we move the script into the visible document immediately and run it, we reliably see syntax errors a portion of the time due to the current chunk breaking script text somewhere in the middle. Our solution is to queue script opening tags and wait until the next node opening tag arrives, or the document closes. There's a second edge case when we move a partial node into the visible document that itself contains scripts, as we then need to attach a second MutationObserver to the appended node since the detached document's MO no longer tracks the moved node. We then repeat the same process in a nested queue per appended element. This seems to work reliably, but isn't great ergonomics and would be greatly simplified if we could instead subscribe to the node's closing tag. ### Animations This is a similar problem to the scripts. We want to animate the replacement of certain elements, and only move/animate them in the visible document once the entire element subtree is complete. Otherwise, the animations will be visually broken. This is complicated relative to the script situation because we can't simply wait for the next opening tag, which may be within the subtree we're trying to animate. We instead need to check every opening tag's ancestor until we find one that is outside the subtree to know the DOM tree to animate is complete. This would again be simplified if we could get a callback when the desired node is finished. ### Performance The MutationObservers in particular come at a measurable cost. For a complex DOM on a modern MacBook Pro, I've ballparked the cost at 100ms+ of MutationObserver time, which can be much slower on mobile devices. So far we've found this to equal or outperform alternative approaches, as using the browser's streaming capabilities both lets us start processing the response sooner, and often more readily breaks the work into smaller chunks. However, we're still understanding the edges and we're seeing enough MO processing time that we could risk violating RAIL guidelines in some scenarios and it would be great to have more performant options when the browser already knows what we need, but we need to hackily reproduce the logic in JS. -- Reply to this email directly or view it on GitHub: https://github.com/WICG/webcomponents/issues/809#issuecomment-1755787377 You are receiving this because you are subscribed to this thread. Message ID: <WICG/webcomponents/issues/809/1755787377@github.com>
Received on Tuesday, 10 October 2023 16:22:41 UTC