Bad performances on rendering huge elements - Is there a concurrent mode for svelte? #10738
Replies: 2 comments
-
The main issue is that insertions/deletions of new elements (e.g. paragraphs) higher up in the text cause a re-creation of most of the structure. This is because the nodes don't have a key or identity that can be tracked by Svelte, so what should leave most of the nodes intact causes them to be destroyed and recreated from scratch. Never used Markdoc but maybe it has a way to better deal with incremental updates. There are two ways in which the situation can be slightly improved:
This will unfortunately not prevent large lag spikes from the element insertions/deletions; Svelte can, to my knowledge, not interrupt this process to handle events. Example of using both debounce & worker: // markdoc-worker.js
import Markdoc from "@markdoc/markdoc";
addEventListener("message", async (event) => {
const { markdown } = event.data;
const ast = Markdoc.parse(markdown);
const node = Markdoc.transform(ast);
postMessage({ ast, node });
}); // debounce.js
export function debounce({
fn,
delay = 300,
maxDelay = 5000, // update at least once every ... ms
}) {
let timeout;
let lastRun = 0;
return function(...args) {
const elapsed = Date.now() - lastRun;
clearTimeout(timeout);
if (elapsed > maxDelay) {
fn(...args);
lastRun = Date.now();
} else {
timeout = setTimeout(() => {
fn(...args);
lastRun = Date.now();
}, delay);
}
};
} <script>
import { initialContent } from "./content.js";
import Renderer from "./renderer.svelte";
// Vite specific import (https://vitejs.dev/guide/features.html#import-with-query-suffixes)
import MarkdocWorker from "./markdoc-worker.js?worker";
import { debounce } from './debounce.js';
let content = initialContent;
let ast;
let node;
const worker = new MarkdocWorker();
worker.addEventListener('message', ({ data }) => {
({ ast, node } = data);
});
const update = debounce({
fn: content => worker.postMessage({ markdown: content }),
});
$: update(content);
// $: worker.postMessage({ markdown: content }) // no debounce
</script> Unless you really need to generate the output via Svelte components, you could also render the full document HTML ( |
Beta Was this translation helpful? Give feedback.
-
Thanks for the amazing answer. Using workers seems to help a lot! Unfortunately the rendering still makes the app lags a bit so if it renders while I'm tying, it's still feels sluggish but I suppose there isn't much I can do about that.
Yeah that was my fear. I searched into it but didn't find anything so I suspected it was the case. The lack of a suspense component for example.
One of the feature of Markdoc is being able to render components so if I have some Svelte component in my markdown then it won't be interactive (something like a dropdown, counter, etc)
Yeah problem is markdoc just regenerates a new tree for everything. I thought about diffing the trees to only update the relevant nodes but I just couldn't do it. I feel like this problem is typically the sort of problem where a vdom framework has the advantage over svelte. That being said web worker seems to be a decent solution as this problem isn't really noticeable unless the document is really large. |
Beta Was this translation helpful? Give feedback.
-
Hey there!
I'm trying to migrate a React app to Sveltekit and I'm having some performances issues with svelte. I'm trying to create an editor experience for Markdoc, a markdoc rendering library. I have a monaco editor running on the left and a preview on the right.
When content gets big, everything becomes super slow and unresponsive. Of course, React is very slow too much I can wrap my updates in startTransition to get able to prevent the main thread from freezing. It seems however that svelte doesn't have a similar escape hatch and I'm therefore stuck.
When you search for concurrent rendering and svelte on google, you only find articles about people dunking on react and how svelte doesn't even need it but my understanding of it is that while svelte performances are better than react, that just moves to problem further down where when your update is big enough, eventually you run into the same problem. React does have an escape hatch though but svelte doesn't seems to have it. I just find threads like these but that doesn't really help me.
#4020
I made a example of what I'm trying to do but the REPL refuses to run recurses too much but it gives a good idea of what's going on.
https://svelte.dev/repl/de92bf1fe3874d4686e1767310b2cccd?version=4.2.12
Here is the user experience with React: (Preview is delayed and renders are cancelled when I'm tying)
Screen.Recording.2024-03-09.at.15.46.09.mov
Here's the svelte experience (Preview updates on every keystroke and the UI just freezes until it's done updating)
Screen.Recording.2024-03-09.at.15.49.06.mov
In the end I just don't know what to do
Beta Was this translation helpful? Give feedback.
All reactions