diff --git a/.changeset/nine-llamas-fetch.md b/.changeset/nine-llamas-fetch.md new file mode 100644 index 000000000000..3219bf2212e2 --- /dev/null +++ b/.changeset/nine-llamas-fetch.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: skip hooks for server fetch to prerendered routes diff --git a/packages/kit/src/runtime/server/fetch.js b/packages/kit/src/runtime/server/fetch.js index 417b59c93063..7aff6629921b 100644 --- a/packages/kit/src/runtime/server/fetch.js +++ b/packages/kit/src/runtime/server/fetch.js @@ -112,6 +112,14 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade return await fetch(request); } + if (manifest._.prerendered_routes.has(decoded)) { + // the prerendered logic is different for each adapter, + // (except maybe for prerendered redirects) + // so we need to make an actual HTTP request + // We do it here to avoid calling server-side hooks for prerendered routes + return await fetch(request); + } + if (credentials !== 'omit') { const cookie = get_cookie_header(url, request.headers.get('cookie')); if (cookie) { diff --git a/packages/kit/src/runtime/server/respond.js b/packages/kit/src/runtime/server/respond.js index 4441e588d3cf..5f5ae7b795e4 100644 --- a/packages/kit/src/runtime/server/respond.js +++ b/packages/kit/src/runtime/server/respond.js @@ -141,7 +141,7 @@ export async function respond(request, options, manifest, state) { return text('Not found', { status: 404, headers }); } - if (!state.prerendering?.fallback && !manifest._.prerendered_routes.has(decoded)) { + if (!state.prerendering?.fallback) { // TODO this could theoretically break — should probably be inside a try-catch const matchers = await manifest._.matchers(); diff --git a/packages/kit/test/apps/basics/src/hooks.server.js b/packages/kit/test/apps/basics/src/hooks.server.js index e485d038d995..1c825a6a6c90 100644 --- a/packages/kit/test/apps/basics/src/hooks.server.js +++ b/packages/kit/test/apps/basics/src/hooks.server.js @@ -1,3 +1,4 @@ +import { building, dev } from '$app/environment'; import { error, isHttpError, redirect } from '@sveltejs/kit'; import { sequence } from '@sveltejs/kit/hooks'; import fs from 'node:fs'; @@ -136,6 +137,15 @@ export const handle = sequence( return resolve(event); }, + async ({ event, resolve }) => { + if (!dev && !building && event.url.pathname === '/prerendering/prerendered-endpoint/api') { + error( + 500, + `Server hooks should not be called for prerendered endpoints: isSubRequest=${event.isSubRequest}` + ); + } + return resolve(event); + }, async ({ event, resolve }) => { if (['/non-existent-route', '/non-existent-route-loop'].includes(event.url.pathname)) { event.locals.url = new URL(event.request.url);