diff --git a/.changeset/friendly-cycles-roll.md b/.changeset/friendly-cycles-roll.md new file mode 100644 index 000000000000..1583855eb6d8 --- /dev/null +++ b/.changeset/friendly-cycles-roll.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +[fix] invalidate implicit dependencies in server load functions diff --git a/packages/kit/src/runtime/server/page/load_data.js b/packages/kit/src/runtime/server/page/load_data.js index 7b12a46fe1c2..07d52db5ff53 100644 --- a/packages/kit/src/runtime/server/page/load_data.js +++ b/packages/kit/src/runtime/server/page/load_data.js @@ -33,6 +33,12 @@ export async function load_server_data({ event, options, state, node, parent }) const result = await node.server.load?.call(null, { ...event, + fetch: (info, init) => { + const url = new URL(info instanceof Request ? info.url : info, event.url); + uses.dependencies.add(url.href); + + return event.fetch(info, init); + }, /** @param {string[]} deps */ depends: (...deps) => { for (const dep of deps) { diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/+page.server.js b/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/+page.server.js new file mode 100644 index 000000000000..9fe91fcff181 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/+page.server.js @@ -0,0 +1,5 @@ +/** @type {import('./$types').PageServerLoad} */ +export async function load({ fetch }) { + const res = await fetch('/load/invalidation/server-fetch/count.json'); + return res.json(); +} diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/+page.svelte b/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/+page.svelte new file mode 100644 index 000000000000..6f25f1b70b45 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/+page.svelte @@ -0,0 +1,5 @@ + + +
{data.count}
diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/count.json/+server.js b/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/count.json/+server.js new file mode 100644 index 000000000000..11116223e5c8 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/server-fetch/count.json/+server.js @@ -0,0 +1,9 @@ +import { json } from '@sveltejs/kit'; + +let count = 0; + +/** @type {import('./$types').RequestHandler} */ +export function GET({ url }) { + if (url.searchParams.has('reset')) count = 0; + return json({ count: count++ }); +} diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index 0a8cc4c66fed..afe4f0f4dc8e 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -1022,6 +1022,16 @@ test.describe('Invalidation', () => { expect(shared).not.toBe(next_shared); }); + test('fetch in server load can be invalidated', async ({ page, app, request }) => { + await request.get('/load/invalidation/server-fetch/count.json?reset'); + await page.goto('/load/invalidation/server-fetch'); + const selector = '[data-testid="count"]'; + + expect(await page.textContent(selector)).toBe('1'); + await app.invalidate('/load/invalidation/server-fetch/count.json'); + expect(await page.textContent(selector)).toBe('2'); + }); + test('+layout.js is re-run when shared dep is invalidated', async ({ page }) => { await page.goto('/load/invalidation/depends'); const server = await page.textContent('p.server'); diff --git a/packages/kit/test/prerendering/basics/test/test.js b/packages/kit/test/prerendering/basics/test/test.js index f4bf390fdf9e..5304db89018f 100644 --- a/packages/kit/test/prerendering/basics/test/test.js +++ b/packages/kit/test/prerendering/basics/test/test.js @@ -188,7 +188,9 @@ test('fetches data from local endpoint', () => { { type: 'data', data: [{ message: 1 }, 'hello'], - uses: {} + uses: { + dependencies: ['http://example.com/origin/message.json'] + } } ] });