Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/unlucky-knives-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

fix: correctly show 404 for prerendered dynamic routes when navigating client-side without a root layout server load
32 changes: 19 additions & 13 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ function update_scroll_positions(index) {
scroll_positions[index] = scroll_state();
}

/**
* Loads `href` the old-fashioned way, with a full page reload.
* Returns a `Promise` that never resolves (to prevent any
* subsequent work, e.g. history manipulation, from happening)
* @param {URL} url
*/
function native_navigation(url) {
location.href = url.href;
return new Promise(() => {});
}

/**
* @param {import('./types.js').SvelteKitApp} app
* @param {HTMLElement} target
Expand Down Expand Up @@ -1196,17 +1207,6 @@ export function create_client(app, target) {
return await native_navigation(url);
}

/**
* Loads `href` the old-fashioned way, with a full page reload.
* Returns a `Promise` that never resolves (to prevent any
* subsequent work, e.g. history manipulation, from happening)
* @param {URL} url
*/
function native_navigation(url) {
location.href = url.href;
return new Promise(() => {});
}

if (import.meta.hot) {
import.meta.hot.on('vite:beforeUpdate', () => {
if (current.error) location.reload();
Expand Down Expand Up @@ -1842,7 +1842,7 @@ export function create_client(app, target) {
/**
* @param {URL} url
* @param {boolean[]} invalid
* @returns {Promise<import('types').ServerNodesResponse |import('types').ServerRedirectNode>}
* @returns {Promise<import('types').ServerNodesResponse | import('types').ServerRedirectNode>}
*/
async function load_data(url, invalid) {
const data_url = new URL(url);
Expand All @@ -1857,13 +1857,19 @@ async function load_data(url, invalid) {

const res = await native_fetch(data_url.href);

// if `__data.json` doesn't exist or the server has an internal error,
// fallback to native navigation so we avoid parsing the HTML error page as a JSON
if (res.headers.get('content-type')?.includes('text/html')) {
await native_navigation(url);
Comment thread
teemingc marked this conversation as resolved.
}

if (!res.ok) {
// error message is a JSON-stringified string which devalue can't handle at the top level
// turn it into a HttpError to not call handleError on the client again (was already handled on the server)
throw new HttpError(res.status, await res.json());
}

// TODO: fix eslint error
// TODO: fix eslint error / figure out if it actually applies to our situation
// eslint-disable-next-line
return new Promise(async (resolve) => {
/**
Expand Down