next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Script blocks hydration/interactivity when using suspense streaming

Open capJavert opened this issue 2 years ago • 5 comments

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

  1. Goto https://nextjs-script-blocks-streaming.vercel.app/
  2. While page is streaming try clicking on the "Clicked" button (you can see the "Loading" text while streaming is happening)
  3. 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

capJavert avatar Nov 07 '22 13:11 capJavert

~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~

capJavert avatar Nov 07 '22 20:11 capJavert

~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.~

capJavert avatar Nov 07 '22 21:11 capJavert

You can ignore my previous two comments, I figured out why the results were inconsistent.

  1. 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..

  2. Also it might be related to HTTP/2 because running next build && next start locally over HTTP/1.1 makes page interactive no matter the Script 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.

capJavert avatar Nov 07 '22 22:11 capJavert

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 🤔

feedthejim avatar Nov 08 '22 10:11 feedthejim

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 ?!

chris-schra avatar Nov 16 '22 19:11 chris-schra

@feedthejim any updates on this one?

capJavert avatar Dec 01 '22 11:12 capJavert

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.

feedthejim avatar Dec 05 '22 14:12 feedthejim