next.js
next.js copied to clipboard
Script blocks hydration/interactivity when using suspense streaming
Verify canary release
- [X] I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 22.1.0: Sun Oct 9 20:15:09 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T6000
Binaries:
Node: 16.13.2
npm: 8.1.2
Yarn: 1.22.18
pnpm: N/A
Relevant packages:
next: 13.0.3-canary.0
eslint-config-next: N/A
react: 18.2.0
react-dom: 18.2.0
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
Vercel
Describe the Bug
While testing new server components and streaming with Suspense
I noticed that any Script
component included on the page/app will block interactivity of the page until streaming is done (eg. all Suspense boundaries are resolved).
I find this weird because Script
with afterInteractive
(which is also a default) strategy do not allow for page to be interactive until all the streaming is done which beats the purpose of streaming.
If I remove Script
from my example I get the Expected Behavior
and page is interactive during streaming.
Expected Behavior
I would expect that page is interactive during streaming just as if there is no Script
components. By interactive I mean any client components on the page should work eg. Click
components from my reproduction example.
Like in this example which does not use Script
: https://nextjs-script-blocks-streaming-git-feat-no-script-capjavert.vercel.app/
Link to reproduction
https://github.com/capJavert/nextjs-script-blocks-streaming
To Reproduce
- Goto https://nextjs-script-blocks-streaming.vercel.app/
- While page is streaming try clicking on the "Clicked" button (you can see the "Loading" text while streaming is happening)
- It will NOT update state or be interactive until after all the Suspense boundaries are loaded and streaming is done ("Loading" text is gone), only then the page will become interactive
~Just jumping in again, I did some more testing after posting this and on latest canary the page is not interactive even if I remove the Script
tag.~
~Branch: https://github.com/capJavert/nextjs-script-blocks-streaming/tree/feat/no-script (single change removed the script tag) Preview (for reproduction): https://nextjs-script-blocks-streaming-1c64fsu9j-capjavert.vercel.app (follow same "To Reproduce" steps~
~I don't know how but this might be Vercel specific, if I build (next build
) and run this locally (next start
) or deploy to anywhere else (outside of Vercel) it works as intended - page is interactive during streaming. 😕~
~Leaving it for today but interested if anyone else finds something.~
You can ignore my previous two comments, I figured out why the results were inconsistent.
-
The initial bug from report IS valid but there was not difference between having a Script or removing it because for some reason if initial document (page) size is small (only few KB) the browser does not hydrate for some reason and page is always not interactive until streaming is done. I guess I would have to look into how browsers like Chrome work but this is the case (I fixed it by adding some content to the page to increase size https://github.com/capJavert/nextjs-script-blocks-streaming/commit/9c1d75661c2eb01a2dd579f6504c93da15ffd643). Maybe this is intended or maybe for another issue..
-
Also it might be related to HTTP/2 because running
next build && next start
locally over HTTP/1.1 makes page interactive no matter theScript
usage. (this is why it looked like Vercel specific https://github.com/vercel/next.js/issues/42582#issuecomment-1306186574)
So to recep, check my initial issue comment I updated the links to the new previews. Using Script
does block interactivity during streaming.
I'm currently investigating this issue. ~~Maybe this can unblock you: I have no idea why this happens yet but adding a useEffect
in the client component made the repro work for me, see https://nextjs-script-blocks-streaming-hjnecg4xe-feedthejim.vercel.app/~~
edit: ignore that, it seems random 🤔
Sorry, I just found that issue when searching for Next 13 Suspense issues. I'm going crazy because Suspense doesn't seem to work for me at all... can someone confirm that ATM the link shared by OP https://nextjs-script-blocks-streaming.vercel.app/ is simply taking a few seconds and then rendering completely, i.e. no "Loading"-element? Or is it really just me? My corporate network settings doing some magic with HTTP ?!
@feedthejim any updates on this one?
Hi @capJavert, sorry we're still looking into it. Some investigation notes: the Script thing is a red herring and we've managed to repro the issue with and without it in a pretty random manner, which makes it fairly difficult to isolate where the problem exactly is.