SSR blank page

Hi everyone, I'm having a little issue in solid start, when I'm using createAsync with the following query, the initial page response is blank, the page has two createAsync, one for the getSession an the other for this request to retrieve the guilds from discord, when there's only the getSession query the initial load of the page has elements rendered from the server and works as expected, I'd appreciate any help on this
No description
No description
No description
34 Replies
SkyLissh
SkyLisshOP2w ago
The suspense was a try to wait for the guilds in the client, but initially I didn't have it, but either using suspense or not, gives me a blank page from SSR
REEEEE
REEEEE2w ago
It's because guilds is read in the memo which causes any above suspense to trigger
SkyLissh
SkyLisshOP2w ago
If I commet the memo and remove the suspense and read the plain value of guilds the issue persists
peerreynders
peerreynders2w ago
This line:
const session = await getMaybeSession();
const session = await getMaybeSession();
The query wrapper is only intended for client side code which includes SSR but not "use server" or pure server code. So what you need to do is factor out getMaybeSession's core into a pure server function and reuse that core function inside getMaybeSession and getSession via an import.
SkyLissh
SkyLisshOP2w ago
It's weird because as I mentioned if I remove all the getGuild logic an leave only the getSession I indeed receive a server rendered page in the first load The blank page from SSR only happens if I cal the getGuild function
peerreynders
peerreynders2w ago
Nevertheless query wrappers are meant for client code, not server code.
SkyLissh
SkyLisshOP2w ago
If I do what you mentioned, wouldn't it mean that the session will be fetched twice if I call the "getMaybeSession" and getSession" in the same page, instead of dedup the request?
peerreynders
peerreynders2w ago
Also if you want SSR rather than streaming use createAsync(…, { deferStream: true }).
wouldn't it mean that the session will be fetched twice if I call the "getMaybeSession" and getSession" in the same page, instead of dedup the request?
What you're doing wouldn't in any way prevent that. Each query is it's own thing and each "use server" is a separate RPC request (unless query results are bundled via single-flight as a result of an action). and you're doing it in getGuilds again:
const session = getSession()
const session = getSession()
So again factor it out to a pure server function and reuse the import in both getSession and getGuilds.
SkyLissh
SkyLisshOP2w ago
I made the following changes, and I still receive a blank page from SSR
No description
No description
No description
No description
SkyLissh
SkyLisshOP2w ago
I change the session queries because error on client, trying to acces environment variable sin client, but the issue persists
No description
SkyLissh
SkyLisshOP2w ago
I think the issue is using fetch
No description
SkyLissh
SkyLisshOP2w ago
This is a different example that causes the same issue
peerreynders
peerreynders2w ago
Is there a suspense boundary above Page?
SkyLissh
SkyLisshOP2w ago
The only Suspense is the default in app.tsx
peerreynders
peerreynders2w ago
That should be enough for SSR.
SkyLissh
SkyLisshOP2w ago
This is the response from the server with the current code
No description
peerreynders
peerreynders2w ago
The fetch as such shouldn't be a problem but the fact it's behaving differently makes me wonder if it has to do with the page streaming. From that perspective I wonder whether adding { deferStream: true } to the createAsyncs would change anything;
SkyLissh
SkyLisshOP2w ago
I try it and yes, it holds the response until it fetches, whys is that? The last time I checked in a toy example, it didn't matter how much time the query took to return, the page didn't load until it was resolved
peerreynders
peerreynders2w ago
Without { deferStream: true } the page doesn't wait until it has all the data to render the full page and just sends what it can render immediately. Once the promises resolve on the server, seroval (de)serializes the data and sends it to the client which renders the rest.
SkyLissh
SkyLisshOP2w ago
Weird, the last time I checked it worked different The doc examples should mention that somewhere
peerreynders
peerreynders2w ago
Your test only provided one guild and I guess a fetch could possibly provide many guilds. Is it possible that one of the other library's interacting with the guild data is trashing the SSR? So perhaps the fetch would start to work if you simply displayed the number of records returned while stripping all the other functionality from Page. I assume in the fetch case you threw in a console.log (to appear on the server side) before the return to ensure that the response data being returned looked sane.
peerreynders
peerreynders2w ago
Unrelated but aside" What made you choose Index instead of For in Page? Index tends to be used when the items are just primitive values because the “DOM-per-item” is then just left in place while the values are just “Re-slotted” when required. For tends to be used with “object items” (keyed) as their “DOM-per-item” is associated with the object's identity and that “DOM-per-item” moves with the “object item” within the list. https://docs.solidjs.com/concepts/control-flow/list-rendering#index-vs-for
List rendering - SolidDocs
Documentation for SolidJS, the signals-powered UI framework
SkyLissh
SkyLisshOP2w ago
Oh, I misunderstood the use, I tought Index was for index that doesn't reorder usually, and For for like reorderable lists or lists that tends to change frequently As far as I tested, the only thing that affects the loading page was the fetch, removing v alibot for example didn't change the result, only when I was removing the fetch And I didn't understand the part of showing only the number of record, what do you mean, making the request but instead of returning the objects just the length of the array? Yup, when I console.log in the server function the data returned by the fetch looks good, and returns pretty fast, idk why in the Page it takes more time
peerreynders
peerreynders2w ago
And I didn't understand the part of showing only the number of record,
The intent was to strip down Page to just SolidStart functionality just to ensure that processing of the actual guild data returned by the fetch wasn't contributing to the defect.
the data returned by the fetch looks good,
One experiment could be to perform the fetch but return the simpler test data. While I expect this would still fail if it actually works it would point towards the data (processing) being the culprit. If it fails another experiment would be to return the test data via a delayed promise in order to determine whether there is some sort of weird timing issue (my guess is that it will still work). Ultimately you can only go only so far diagnosing this by code review. The actual problem could still be upstream of the fetch, the fetch just being the needle that breaks the camel's back. Countless times the actual root causes to issues in the support channel aren't actually found within the code that was presented during the support discussion.
SkyLissh
SkyLisshOP2w ago
Idk if it could be affecting, but in the project I'm using bun as a package manager and for running the commands I se bun dev as fas as I know bun uses nodefor running vite I didn't check but with the refactor for session I made yesterday, know it also returns a blank page when using only the session query and previous to the change it was pre rendering whe using only that query I will make a build to check if it works properly in prod, and if the error is only in dev It al;so happens in prod, but it's kinda weird, because, it feels like I'm getting a server renderd page in time, but the response is a blank page The only thing I can imagine is messing up with the SSR is the paraglidemiddleware @peerreynders Well I think it would be much easier if I provide all the code, so here's my repo with all the stuff I trying to do https://github.com/SkyLissh/skylet-discord-dashboard/tree/feature/auth
SkyLissh
SkyLisshOP2w ago
I made a new project and created a simple example with a fetch, I just added the example query, and the result is the same, a blank page
No description
peerreynders
peerreynders2w ago
import { Title } from '@solidjs/meta';
import { createAsync, query, RouteDefinition } from '@solidjs/router';
import Counter from '~/components/Counter';

const example = query(async () => {
'use server';
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
return response.json();
}, 'example');

export default function Home() {
const myExample = createAsync(() => example());

return (
<main>
<Title>Hello World</Title>
<h1>Hello world!</h1>
<Counter />
<pre>{JSON.stringify(myExample(), null, 2)}</pre>
<p>
Visit{' '}
<a href="https://start.solidjs.com" target="_blank">
start.solidjs.com
</a>{' '}
to learn how to build SolidStart apps.
</p>
</main>
);
}
import { Title } from '@solidjs/meta';
import { createAsync, query, RouteDefinition } from '@solidjs/router';
import Counter from '~/components/Counter';

const example = query(async () => {
'use server';
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
return response.json();
}, 'example');

export default function Home() {
const myExample = createAsync(() => example());

return (
<main>
<Title>Hello World</Title>
<h1>Hello world!</h1>
<Counter />
<pre>{JSON.stringify(myExample(), null, 2)}</pre>
<p>
Visit{' '}
<a href="https://start.solidjs.com" target="_blank">
start.solidjs.com
</a>{' '}
to learn how to build SolidStart apps.
</p>
</main>
);
}
Runs without issue: node: v22.14.0 pnpm: 10.7.1 Ubuntu 22.04.5 LTS
Madaxen86
Madaxen862w ago
That’s probably a bun thing. There’s an issue : https://github.com/oven-sh/bun/issues/11381 may be unrelated. And I found this: "Vinxi project such as solid-start doesn't work with Deno 2.0 Here is a repo: https://github.com/Ciantic/deno-solid-test This most likely because Vinxi runs node.exe behind the scenes instead of deno.exe. It's notable that bun also has same error, but it can be fixed by using a flag --bun that fakes bun.exe as node.exe."
GitHub
Bun does not implement fetch() API correctly · Issue #11381 · o...
What version of Bun is running? 1.1.8 What platform is your computer? Linux 5.15.146.1-microsoft-standard-WSL2 x86_64 x86_64 What steps can reproduce the bug? Bun malforms request when using overlo...
zulu
zulu2w ago
bad code delete it all
SkyLissh
SkyLisshOP7d ago
But in the network tab you receive a pre rendered page? I made the same example with node: 22.13.1 and pnpm: 10.8.0
peerreynders
peerreynders7d ago
I wouldn't expect to given that { deferStream: true } wasn't used. i.e. it would only be partially rendered.
SkyLissh
SkyLisshOP7d ago
So by default solidjs use something like partial pre rendering in nextjs, instead of waiting for the data called in the queries? I think I didn't understand at first because every other framework by the default waits the page, and only do partially pre-rendering when you specify to do so
peerreynders
peerreynders7d ago
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<script>
// … hydration listener
</script>
<script>
// … more
</script>
<!--xs-->
<script
type="module"
src="…/node_modules/vinxi/runtime/client.js"
id="plugin-0"
></script>
<script type="module" src="/_build/@vite/client" id="vite-client"></script>
<style type="text/css" data-vite-dev-id="…/src/app.css" data-vite-ref="0">
/* … css */
</style>
<title data-sm="00000000100000300000120">Hello World</title>
</head>
<body>
<div id="app">
<!--!$e0000000--><a data-hk="000000001000001" href="/">Index</a
><a data-hk="000000001000002" href="/about">About</a
><template id="pl-0000000010000030"></template
><!--pl-0000000010000030--><!--!$/e0000000-->
</div>
<!--$-->
<script>
// …
</script>
<script type="module" async src="…/src/entry-client.tsx"></script>
<!--/-->
</body>
</html>
<template id="0000000010000030"
><style
data-hk="000000001000003000000"
type="text/css"
data-vite-dev-id="../src/components/Counter.css"
data-vite-ref="0"
>
/* … css */
</style>
<main data-hk="0000000010000030000011">
<!--$--><!--/-->
<h1>Hello world!</h1>
<!--$--><button
data-hk="00000000100000300000130"
class="increment"
type="button"
>
Clicks:
<!--$-->0<!--/--></button
><!--/-->
<pre>
<!-- rendered JSON data -->
</pre>
<p>
Visit
<a href="https://start.solidjs.com" target="_blank">start.solidjs.com</a>
to learn how to build SolidStart apps.
</p>
</main></template
>
<script>
// … lots of seroval code streaming the async data in
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<script>
// … hydration listener
</script>
<script>
// … more
</script>
<!--xs-->
<script
type="module"
src="…/node_modules/vinxi/runtime/client.js"
id="plugin-0"
></script>
<script type="module" src="/_build/@vite/client" id="vite-client"></script>
<style type="text/css" data-vite-dev-id="…/src/app.css" data-vite-ref="0">
/* … css */
</style>
<title data-sm="00000000100000300000120">Hello World</title>
</head>
<body>
<div id="app">
<!--!$e0000000--><a data-hk="000000001000001" href="/">Index</a
><a data-hk="000000001000002" href="/about">About</a
><template id="pl-0000000010000030"></template
><!--pl-0000000010000030--><!--!$/e0000000-->
</div>
<!--$-->
<script>
// …
</script>
<script type="module" async src="…/src/entry-client.tsx"></script>
<!--/-->
</body>
</html>
<template id="0000000010000030"
><style
data-hk="000000001000003000000"
type="text/css"
data-vite-dev-id="../src/components/Counter.css"
data-vite-ref="0"
>
/* … css */
</style>
<main data-hk="0000000010000030000011">
<!--$--><!--/-->
<h1>Hello world!</h1>
<!--$--><button
data-hk="00000000100000300000130"
class="increment"
type="button"
>
Clicks:
<!--$-->0<!--/--></button
><!--/-->
<pre>
<!-- rendered JSON data -->
</pre>
<p>
Visit
<a href="https://start.solidjs.com" target="_blank">start.solidjs.com</a>
to learn how to build SolidStart apps.
</p>
</main></template
>
<script>
// … lots of seroval code streaming the async data in
</script>
Result from “View Page Source”.
instead of waiting for the data called in the queries?
SolidStart's default SSR behaviour is to render synchronously what it can and stream the rest in via seroval via a streaming response to the initial request (which I did mention earlier, here).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<script>
// … hydration listener
</script>
<script>
// … seroval data already
</script>
<!--xs-->
<script
type="module"
src="…/node_modules/vinxi/runtime/client.js"
id="plugin-0"
></script>
<script type="module" src="/_build/@vite/client" id="vite-client"></script>
<style type="text/css" data-vite-dev-id="…/src/app.css" data-vite-ref="0">
/* … css */
</style>
<title data-sm="00000000100000300000120">Hello World</title>
</head>
<body>
<div id="app">
<!--!$e0000000--><a data-hk="000000001000001" href="/">Index</a
><a data-hk="000000001000002" href="/about">About</a
><style
data-hk="000000001000003000000"
type="text/css"
data-vite-dev-id="…/src/components/Counter.css"
data-vite-ref="0"
>
/* … css */
</style>
<main data-hk="0000000010000030000011">
<!--$--><!--/-->
<h1>Hello world!</h1>
<!--$--><button
data-hk="00000000100000300000130"
class="increment"
type="button"
>
Clicks:
<!--$-->0<!--/--></button
><!--/-->
<pre><!-- rendered JSON data --></pre>
<p>
Visit
<a href="https://start.solidjs.com" target="_blank"
>start.solidjs.com</a
>
to learn how to build SolidStart apps.
</p>
</main>
<!--!$/e0000000-->
</div>
<!--$-->
<script>
// …
</script>
<script type="module" async src="…/src/entry-client.tsx"></script>
<!--/-->
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<script>
// … hydration listener
</script>
<script>
// … seroval data already
</script>
<!--xs-->
<script
type="module"
src="…/node_modules/vinxi/runtime/client.js"
id="plugin-0"
></script>
<script type="module" src="/_build/@vite/client" id="vite-client"></script>
<style type="text/css" data-vite-dev-id="…/src/app.css" data-vite-ref="0">
/* … css */
</style>
<title data-sm="00000000100000300000120">Hello World</title>
</head>
<body>
<div id="app">
<!--!$e0000000--><a data-hk="000000001000001" href="/">Index</a
><a data-hk="000000001000002" href="/about">About</a
><style
data-hk="000000001000003000000"
type="text/css"
data-vite-dev-id="…/src/components/Counter.css"
data-vite-ref="0"
>
/* … css */
</style>
<main data-hk="0000000010000030000011">
<!--$--><!--/-->
<h1>Hello world!</h1>
<!--$--><button
data-hk="00000000100000300000130"
class="increment"
type="button"
>
Clicks:
<!--$-->0<!--/--></button
><!--/-->
<pre><!-- rendered JSON data --></pre>
<p>
Visit
<a href="https://start.solidjs.com" target="_blank"
>start.solidjs.com</a
>
to learn how to build SolidStart apps.
</p>
</main>
<!--!$/e0000000-->
</div>
<!--$-->
<script>
// …
</script>
<script type="module" async src="…/src/entry-client.tsx"></script>
<!--/-->
</body>
</html>
“View Page Source” after:
export default function Home() {
const myExample = createAsync(() => example(), { deferStream: true });

return {
/* same ol' JSX */
};
}
export default function Home() {
const myExample = createAsync(() => example(), { deferStream: true });

return {
/* same ol' JSX */
};
}
zulu
zulu7d ago
good, you deleted, change your access token

Did you find this page helpful?