Static page not showing suspense states
Unanswered
Telomian posted this in #help-forum
TelomianOP
I have a page marked as static (am using force-static). When the page is compiled on the fly - during the request the user makes - the page just loads without any of the intermittent suspense boundaries showing. Is there a way to use suspense for static pages?
29 Replies
@Telomian I have a page marked as static (am using force-static). When the page is compiled on the fly - during the request the user makes - the page just loads without any of the intermittent suspense boundaries showing. Is there a way to use suspense for static pages?
Hmm I don’t think I follow. The whole point of a static page is that it is built ahead of time so can be served instantly, making any intermediary loading states redundant. So it’s only expected that static pages don’t have a loading state when served
TelomianOP
@joulev right but for ISR pages that haven't been compiled yet, the 1st request blocks until it is compiled entirely - making it weird user experience
@Telomian <@484037068239142956> right but for ISR pages that haven't been compiled yet, the 1st request blocks until it is compiled entirely - making it weird user experience
that's weird, it should show the loading page in that case. can you show your code?
TelomianOP
@joulev sure let me get a repro 1 sec
TelomianOP
@joulev here's a repro https://github.com/lmatteis/nextjs-static-suspense
@Telomian <@484037068239142956> here's a repro https://github.com/lmatteis/nextjs-static-suspense
yeah honestly looks like a bug to me, i suggest you report it on github
TelomianOP
So weird 😦
i found the issue but it's been dormant
https://github.com/vercel/next.js/issues/50215
https://github.com/vercel/next.js/issues/50215
Not much we can do about that
If you tell me your use case I may be able to come up with some workaround
TelomianOP
@joulev well, the use case is that we have a simple blog. a blog page does many requests to different sources so can take like 4 seconds to compile. when the blog page is accessed for the first time it just hangs for that user without showing anything
@Telomian <@484037068239142956> well, the use case is that we have a simple blog. a blog page does many requests to different sources so can take like 4 seconds to compile. when the blog page is accessed for the first time it just hangs for that user without showing anything
in that case you should be able to use generateStaticParams right?
TelomianOP
@joulev that's only at build time, no? imagine a new blog page is created in the database. accessing that new page will block
maybe a better UX would be to 404 instead of blocking? not sure that's possible
@Telomian <@484037068239142956> that's only at build time, no? imagine a new blog page is created in the database. accessing that new page will block
that particular case, loading.tsx should work. i think this bug is limited to force-static only
because ISR using generateStaticParams() with loading.tsx is a pretty common use case
if it breaks, it would be pretty bad
TelomianOP
indeed, i have also a repro here: https://github.com/vercel/next.js/issues/80774
i can try without 'force-static' ...
it's the same even if the page is marged with SSG
TelomianOP
all i want is ISR, but that it shows suspense for when the page is new
it seems like Suspense/loading.tsx is not working at all in ISR setups
@Telomian all i want is ISR, but that it shows suspense for when the page is new
wow, i can confirm now it is completely broken for me too.
well... why am i not surprised
let's wait for them to fix this which will probably take forever at this rate. not much else we can do about it though.
maybe you can configure a webhook so that whenever a new page is added, a request to the slug is automatically made, or you automatically call
well... why am i not surprised
let's wait for them to fix this which will probably take forever at this rate. not much else we can do about it though.
maybe you can configure a webhook so that whenever a new page is added, a request to the slug is automatically made, or you automatically call
revalidatePath
or something, so that it is fetched and cached as soon as possibleTomistoma
@Telomian loading.tsx and Suspense boundaries are primarily designed to show a loading state during client-side navigation or when data is being fetched asynchronously on the client. When Next.js server-renders a page from scratch on the first request for an ungenerated ISR path, it's a synchronous process on the server. The server doesn't "suspend" and then stream a loading state; it builds the complete HTML and sends it.
* No Client-Side Hydration Yet: For the very first render of an ungenerated page, the client hasn't received any JavaScript yet to hydrate the page and enable client-side React features like Suspense. It's a pure HTML response.
As @joulev suggest we can use revalidate webhook for that new path so it will generate static page as soon as possible. and of course it will also be helpfull for already generated pages. for example if someone made changes for particular blogpost which page already has been generated it will be also regenrate on revalidate call.
* No Client-Side Hydration Yet: For the very first render of an ungenerated page, the client hasn't received any JavaScript yet to hydrate the page and enable client-side React features like Suspense. It's a pure HTML response.
As @joulev suggest we can use revalidate webhook for that new path so it will generate static page as soon as possible. and of course it will also be helpfull for already generated pages. for example if someone made changes for particular blogpost which page already has been generated it will be also regenrate on revalidate call.
@Tomistoma <@105799799382523904> loading.tsx and Suspense boundaries are primarily designed to show a loading state during client-side navigation or when data is being fetched asynchronously on the client. When Next.js server-renders a page from scratch on the first request for an ungenerated ISR path, it's a synchronous process on the server. The server doesn't "suspend" and then stream a loading state; it builds the complete HTML and sends it.
* No Client-Side Hydration Yet: For the very first render of an ungenerated page, the client hasn't received any JavaScript yet to hydrate the page and enable client-side React features like Suspense. It's a pure HTML response.
As <@484037068239142956> suggest we can use revalidate webhook for that new path so it will generate static page as soon as possible. and of course it will also be helpfull for already generated pages. for example if someone made changes for particular blogpost which page already has been generated it will be also regenrate on revalidate call.
Well the server does suspend, or at least it is supposed to suspend. It not suspending is a bug, not intended behaviour.
https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#:~:text=the%20segment%20uses%20Streaming%20Server%20Rendering.
https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#:~:text=the%20segment%20uses%20Streaming%20Server%20Rendering.
TelomianOP
@Tomistoma thanks but revalidatePath/Tag is the same. it purges the item from cache, making the next first generation blocking
@Tomistoma is there a conceptual reason for it not to show the loading states and stream in as if it were dynamic on the intial compilation? even if it has to send the javascript, it would still be a better UX than just a blank page
i think the reson it's blocking is that it needs to somehow generate the HTML without loading states to put in cache (so it can be served on subsequent requests)
so sending the dynamic loading stream to the client while generating the static HTML could be double the work