Skip to content

Commit 9909a29

Browse files
fix: wait an extra microtask in dev before calling $$_init_$$ (#14799)
1 parent dc33ef7 commit 9909a29

File tree

8 files changed

+60
-1
lines changed

8 files changed

+60
-1
lines changed

.changeset/empty-animals-retire.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: wait an extra microtask in dev before calling `$$_init_$$`

packages/kit/src/exports/vite/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,13 +698,21 @@ async function kit({ svelte_config }) {
698698
remotes.push(remote);
699699

700700
if (opts?.ssr) {
701+
// we need to add an `await Promise.resolve()` because if the user imports this function
702+
// on the client AND in a load function when loading the client module we will trigger
703+
// an ssrLoadModule during dev. During a link preload, the module can be mistakenly
704+
// loaded and transformed twice and the first time all its exports would be undefined
705+
// triggering a dev server error. By adding a microtask we ensure that the module is fully loaded
706+
701707
// Extra newlines to prevent syntax errors around missing semicolons or comments
702708
code +=
703709
'\n\n' +
704710
dedent`
705711
import * as $$_self_$$ from './${path.basename(id)}';
706712
import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal';
707713
714+
${dev_server ? 'await Promise.resolve()' : ''}
715+
708716
$$_init_$$($$_self_$$, ${s(file)}, ${s(remote.hash)});
709717
710718
for (const [name, fn] of Object.entries($$_self_$$)) {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script lang="ts">
2+
import { resolve } from '$app/paths';
3+
</script>
4+
5+
<a href={resolve('/remote/dev/preload')} data-sveltekit-preload-data="hover">preload</a>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { example } from './example.remote';
2+
3+
export const load = async () => {
4+
return {
5+
example: await example('bar')
6+
};
7+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script>
2+
import { example } from './example.remote';
3+
4+
export let data;
5+
</script>
6+
7+
<p>{data.example}</p>
8+
<button onclick={async () => (data.example = await example('baz'))}>Refresh</button>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { query } from '$app/server';
2+
import { schema } from './schema';
3+
4+
export const example = query(schema, async (param) => {
5+
await new Promise((resolve) => setTimeout(resolve, 1000));
6+
return 'foo' + param;
7+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import * as v from 'valibot';
2+
3+
export const schema = v.string();

packages/kit/test/apps/basics/test/client.test.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,8 +1786,24 @@ test.describe('routing', () => {
17861786
});
17871787
});
17881788

1789-
// have to run in serial because commands mutate in-memory data on the server
17901789
test.describe('remote functions', () => {
1790+
test('preloading data works when the page component and server load both import a remote function', async ({
1791+
page
1792+
}) => {
1793+
test.skip(!process.env.DEV, 'remote functions are only analysed in dev mode');
1794+
await page.goto('/remote/dev');
1795+
await page.locator('a[href="/remote/dev/preload"]').hover();
1796+
await Promise.all([
1797+
page.waitForTimeout(100), // wait for preloading to start
1798+
page.waitForLoadState('networkidle') // wait for preloading to finish
1799+
]);
1800+
await page.click('a[href="/remote/dev/preload"]');
1801+
await expect(page.locator('p')).toHaveText('foobar');
1802+
});
1803+
});
1804+
1805+
// have to run in serial because commands mutate in-memory data on the server
1806+
test.describe('remote function mutations', () => {
17911807
test.describe.configure({ mode: 'default' });
17921808
test.afterEach(async ({ page }) => {
17931809
if (page.url().endsWith('/remote')) {

0 commit comments

Comments
 (0)