Skip to content

Commit 622e49f

Browse files
committed
fix: don't wait for remote functions that are not awaited in the template
Fixes #15200
1 parent 3cbaac2 commit 622e49f

File tree

5 files changed

+60
-1
lines changed

5 files changed

+60
-1
lines changed

.changeset/large-squids-pull.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: don't wait for remote functions that are not awaited in the template

packages/kit/src/runtime/server/page/render.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,22 @@ export async function render_response({
493493
if (!info.id) continue;
494494

495495
for (const key in cache) {
496-
remote[create_remote_key(info.id, key)] = await cache[key];
496+
// Don't block the response on pending remote data — if a query
497+
// hasn't settled yet (e.g. caught by a svelte:boundary), skip it
498+
// and let the client fetch it instead via the remote function stub.
499+
const result = await Promise.race([
500+
Promise.resolve(cache[key]).then(
501+
(v) => /** @type {const} */ ({ settled: true, value: v }),
502+
() => /** @type {const} */ ({ settled: false })
503+
),
504+
new Promise((resolve) => {
505+
queueMicrotask(() => resolve(/** @type {const} */ ({ settled: false })));
506+
})
507+
]);
508+
509+
if (result.settled) {
510+
remote[create_remote_key(info.id, key)] = result.value;
511+
}
497512
}
498513
}
499514

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script>
2+
import { get_delayed_data, get_fast_data } from './data.remote.js';
3+
4+
// shouldn't block SSR since requested immediately but awaited inside pending boundary
5+
const delayed = get_delayed_data();
6+
</script>
7+
8+
<p id="fast-result">{await get_fast_data()}</p>
9+
<svelte:boundary>
10+
{#snippet pending()}
11+
<p id="delayed-pending">loading delayed</p>
12+
{/snippet}
13+
<p id="delayed-result">{await delayed}</p>
14+
</svelte:boundary>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { query } from '$app/server';
2+
3+
export const get_delayed_data = query(async () => {
4+
await new Promise((resolve) => setTimeout(resolve, 2000));
5+
return 'delayed data';
6+
});
7+
8+
export const get_fast_data = query(() => {
9+
return 'fast data';
10+
});

packages/kit/test/apps/async/test/test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,4 +482,19 @@ test.describe('remote functions', () => {
482482
})
483483
);
484484
});
485+
486+
test('query stored as variable does not block SSR inside boundary', async ({
487+
page,
488+
javaScriptEnabled
489+
}) => {
490+
await page.goto('/remote/query-boundary');
491+
492+
await expect(page.locator('#delayed-pending')).toHaveText('loading delayed');
493+
494+
if (javaScriptEnabled) {
495+
await expect(page.locator('#delayed-result')).toHaveText('delayed data', {
496+
timeout: 5000
497+
});
498+
}
499+
});
485500
});

0 commit comments

Comments
 (0)