-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Description
Describe the bug
Sorry I haven't created a more isolated example but encountered this issue and found a workaround today and wanted to submit an issue in case it helps reveal the root cause.
In the new LayerChart docs we load examples into context (based on the current page usage) and then retrieve them (either by relative path or component/name) in an Example component.
We were using let example = $derived.by(...) to retrieve the example and worked great EXCEPT when we would update +layout.svelte or any other component on the page (including Example) and trigger a HMR, it would cause the CPU to spike to 100% and continuously trigger re-renders of the Example component.
Here is relevant code (but see Example for more context)
<script>
let example = $derived.by(() => {
if (path) {
// Path-based example
const resolvedPath = resolveExamplePath(path, page.url.pathname);
return examples.get()?.current['__path__']?.[resolvedPath];
} else if (component && name) {
// Component/name-based example
return examples.get()?.current[component]?.[name];
}
return undefined;
});
</script>
{#if example}
<example.component />
{/if}Interestingly, if you commented out <example.component /> it would no longer cause the spike.
I tried a multitude of solutions / workarounds ({#key}, {@const Component = example.component}, let Component = $derived(example?.component), remove bind:ref) but the only workaround I found was to replace the $derived.by() with $state and $effect (which is counter to typical recommendations).
// Use $state + $effect to break potential infinite reactivity loops during HMR
<script>
let example = $state<{ component: any; source: string } | undefined>(undefined);
$effect(() => {
if (path) {
// Path-based example
const resolvedPath = resolveExamplePath(path, page.url.pathname);
example = examples.get()?.current['__path__']?.[resolvedPath];
} else if (component && name) {
// Component/name-based example
example = examples.get()?.current[component]?.[name];
} else {
example = undefined;
}
});
</script>
{#if example}
<example.component />
{/if}We haven't tried downgrading Svelte versions after finding this workaround as the project is always gingerly walking between many async/remote function pain points (rolling back to an older version sometimes fix one thing and re-introduces another). Without testing, but my first intuition is it could be caused by #17105.
We know what we signed up for using experimental async/ remote functions 🤣
Reproduction
This is part of a big docs-v2 PR we're working on. You can check out the PR and run pnpm dev.
Logs
System Info
`svelte@5.46.0` with experimental async enabled, `@sveltejs/kit@2.49.2` with experimental remote functions enabledSeverity
blocking an upgrade