Closed kevinrenskers closed 1 year ago
The problem is that you are running an asynchronous operation inside the server context. Svelte can't really detect that and breaks, because while doing server side rendering, everything runs in one go synchronously, and by the time fetchContent
resolves the component context no longer exists.
Wrap your fetchContent.then(..)
inside if (browser) { .. }
and it works.
This isn't really an issue with SvelteKit, rather a gotcha with Svelte server rendering itself, therefore closing.
It's strange how moving the exact same code to +page.ts
does work, async operation and all.
// +page.ts
import { get, writable, readable, type Writable } from "svelte/store";
import { browser } from "$app/environment";
import type { PageLoad } from "./$types";
export const load: PageLoad = async ({ parent }) => {
const locationsStore: Writable<{ id: number; name: string }[]> = writable();
if (browser && get(locationsStore)) {
return { locations: locationsStore };
}
const fetchedValues = [{ id: 1, name: "Test" }];
if (browser) {
locationsStore.set(fetchedValues);
return { locations: locationsStore };
} else {
return { locations: readable(fetchedValues) };
}
};
// +page.svelte
<script lang="ts">
import type { PageData } from "./$types";
export let data: PageData;
const locations = data.locations;
</script>
{#each $locations as location}
{location.id}: {location.name}
{/each}
In my real-world app it's actually a reusable component that calls this fetchContent
function, so it's not as easy to refactor. I guess I just have to pass in the fetched content, which the page has to give it, and the fetching has to be done in +page.ts
. But since the component is shown conditionally that means I'd be overfetching in some scenarios.
Adding the if (browser) { .. }
like you suggested works, but then you have a flash of content appearing because the SSR version doesn't have the content, which isn't great.
I really wish SvelteKit would make async operation in components and pages work reliably for SSR, just like it can do in +page.ts
.
Describe the bug
I have a problem where if I reach a certain page from client side navigation everything works fine. But if I then reload that page, the dev server crashes with the following:
Reproduction
I have a repro project at https://github.com/kevinrenskers/sveltekit-store-crash.
System Info
Severity
"Blocking all usage of SvelteKit"
Well, I am already using SvelteKit in production so that is not completely true. But it is blocking me from pushing a brand new feature to the website which now 100% breaks when reloading the website.
Additional Information
To explain a bit what my sample code is doing: in my real-world app I have centralized writable stores for a whole bunch of content, which is fetched from an external API. The real
fetchContent
function does the API request, and then the logic is basically the same: first check if we already have the content stored, if not do the API request. Then, if we're in the browser, store the fetched content in our store, otherwise just return a new readable store.That way the page always has a readable store of content to work with, and all the cashing happens behind the scene.
The sample code is simplified to return hardcoded content and all the code is within one page, whereas in the real application the store and the
fetchContent
are within thelib
folder, but the error is the same.