Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inconsistencies with streaming and Suspense on vercel #51033

Closed
1 task done
Fredkiss3 opened this issue Jun 9, 2023 · 38 comments
Closed
1 task done

inconsistencies with streaming and Suspense on vercel #51033

Fredkiss3 opened this issue Jun 9, 2023 · 38 comments
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template. locked Navigation Related to Next.js linking (e.g., <Link>) and navigation. Pages Router Related to Pages Router.

Comments

@Fredkiss3
Copy link
Contributor

Verify canary release

  • 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 23.0.0: Mon May 22 22:50:46 PDT 2023; root:xnu-10002.0.40.505.5~4/RELEASE_ARM64_T8103
    Binaries:
      Node: 18.0.0
      npm: 8.6.0
      Yarn: 1.22.18
      pnpm: 7.19.0
    Relevant packages:
      next: 13.4.5-canary.9
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.1.3

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), Data fetching (gS(S)P, getInitialProps), Routing (next/router, next/navigation, next/link)

Link to the code that reproduces this issue or a replay of the bug

https://github.com/Fredkiss3/vercel-streaming-bug

To Reproduce

Go to the vercel-streaming-bug.vercel.app, check the wait checkbox and enter any pokemon name.

You may see that the page will wait for at least 2s before showing anything, you can retry with different names, and sometimes the fallback will be shown, but most of the time the page will block and immediatly return the new list of pokemons.

Describe the Bug

The bug is that in when deploying a next app to vercel, the Suspense fallback is not always shown and it blocks instead of showing a fallback. Even when the page clearly use edge runtime (so streaming should be enabled).

Expected Behavior

I tested on different providers to be sure :

On other providers, the fallback is always shown and the request is streamed correctly but on vercel sometimes it blocks before showing anything.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

vercel

@Fredkiss3 Fredkiss3 added the bug Issue was opened via the bug report template. label Jun 9, 2023
@github-actions github-actions bot added area: app App directory (appDir: true) Pages Router Related to Pages Router. Navigation Related to Next.js linking (e.g., <Link>) and navigation. labels Jun 9, 2023
@Frost7994
Copy link

Also having this issue

@YoussefKababe
Copy link

YoussefKababe commented Jun 11, 2023

Found this in the docs:

To change the default framework behavior. For example, Suspense Boundaries inside layouts only show the fallback the first time the Layout is loaded and not when switching pages. For templates, the fallback is shown on each navigation.

My issue is a bit different, but for this one I think using templates is the answer? Not sure...

@Fredkiss3
Copy link
Contributor Author

@YoussefKababe
I'm not even using layouts, the fallback is in a page.tsx file. and i don't even know how i could rearchitect the app to use templates.

Another thing : this issue only happen on vercel. so this is not simply a next.js issue... i think.

@Frost7994
Copy link

I'm having an issue where I have a component wrapped in suspense with a fallback, the component fetches data with an artificial delay, on navigating to the page it looks for a loading.js page as per NextJS docs and if none is found it blocks the page render until the data is fetched. However, if I reload the page suspense does work. An example is below.

// /dashboard.js

import { Suspense } from "react";
import PostList from "./postList";
import Header from './header';
import Link from "next/link";

const Dashboard = async () => {
  return (
    <div className="p-8">
      <Header />
      <Suspense fallback={<div>Loading...</div>}>
        <PostList />
      </Suspense>
    </div>
  );
};

export default Dashboard;

and

// /dashboard/postList.js

const PostList = async () => {
  const fetchDataWithDelay = async () => {
    const res = await fetch(
      "https://jsonplaceholder.typicode.com/posts?userId=3",
      {
        cache: "no-store",
      }
    );
    const data = await res.json();

    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(data);
      }, 3000);
    });
  };

  const data = await fetchDataWithDelay();

  return (
    <ul className="flex flex-col gap-2">
      {data.map((post) => (
        <li
          key={post.id}
          className="flex flex-col border rounded-md border-slate-500 p-4"
        >
          <h4 className="text-lg font-medium">{post.title}</h4>
          <p className="text-slate-500">{post.body}</p>
        </li>
      ))}
    </ul>
  );
};

export default PostList;

@matt-kruse
Copy link

I seem to be having this same issue. Suspense/Streaming seems like such a core RSC feature to be broken, right? I couldn't believe it was a bug and I spent hours trying to get it to work. Streaming is one of the biggest selling points of RSC!

Simple example below. This waits for 5 seconds on the server, rather than returning immediately and streaming in the Suspense content.
https://demystifying-rsc.vercel.app/suspense-test/
Code:

import {Suspense} from "react";
export const dynamic='force-dynamic';

async function Delay() {
  return new Promise(r=>{
    setTimeout(()=>r(<div>Delayed Content: {Date.now()}</div>),5000);
  });
}
export default async()=>{
  return <Suspense fallback={<div>Loading...</div>}><Delay/></Suspense>
}

@Fredkiss3
Copy link
Contributor Author

@matt-kruse the issue is more vercel related than next related. If you deploy your app to cloudfare Suspense will work as expected.

@matt-kruse
Copy link

@matt-kruse the issue is more vercel related than next related. If you deploy your app to cloudfare Suspense will work as expected.

Is there any better way to report this to Vercel or get visibility to the problem?

@Fredkiss3
Copy link
Contributor Author

I don't know

@markkkkas
Copy link

cc @leerob

@leerob
Copy link
Member

leerob commented Jun 20, 2023

Let me check to see if this is indeed a Vercel issue, and if so, we can transfer this issue over to the Vercel GitHub Discussions and keep looking into this. Thanks for the reproduction!

@matt-kruse
Copy link

Thanks @leerob - If it does transfer somewhere else, please let us know where we can track it.

@matt-kruse
Copy link

I've discovered that my link does in fact work for most people. I am behind a work proxy and zscaler, which is apparently interfering with Transfer-Encoding:chunked in some way? Or buffering the chunked content until the document is complete? I'm not sure yet, exactly. But it's definitely something with MITM that is causing it not to stream for me.

@james-william-r
Copy link

This seems to be fixed (or at least vastly improved - can’t quite tell yet) in the release that dropped yesterday. 👌

@Fredkiss3
Copy link
Contributor Author

@james-william-r I just upgraded next to the latest canary version and the issue still persist.

@james-william-r
Copy link

Weird, is massively improved for me. 🤷

@Fredkiss3
Copy link
Contributor Author

How has it massively improved ? In what sense ?

@james-william-r
Copy link

Ignore me, it's still very much an issue. 🙃

@YoussefKababe
Copy link

Any update from the Vercel team on this one? Streaming still not working correctly and it's one the biggest selling features of the platform...

@matt-kruse
Copy link

Any update from the Vercel team on this one? Streaming still not working correctly and it's one the biggest selling features of the platform...

Have you verified that you aren't behind a buffering proxy? That was my issue. Once I used a different wifi with no proxy streaming worked fine.

@Fredkiss3
Copy link
Contributor Author

@matt-kruse , in my case, i don't use a proxy that could buffer the response (at least that i know) and the weird part is that it happens only on vercel for me, on cloudfare and railway, streaming works without a problem and the suspense fallback is always shown.

@Fredkiss3
Copy link
Contributor Author

@matt-kruse Question : Is the suspense fallback always showing for you when you try the vercel example i've given here ?

Go to the vercel-streaming-bug.vercel.app, check the wait checkbox and enter any pokemon name.

You may see that the page will wait for at least 2s before showing anything, you can re
try with different names, and sometimes the fallback will be shown, but most of the time the page will block and immediatly return the new list of pokemons.

@juliendelort
Copy link

Here is another minimal reproduction: https://codesandbox.io/p/sandbox/cocky-babycat-rrw649

The suspense fallback is shown on first page load but not when clicking on either link (the page just hangs for 3 seconds and then the UI is updated).

@Fredkiss3
Copy link
Contributor Author

hey @juliendelort , by default suspense do not show the fallback everytime when used on searchParams, i added a key to Suspense and that's what makes it show everytime : https://github.com/Fredkiss3/vercel-streaming-bug/blob/4f6a356f67fd0a034d9f148e8588dcb0319e0e45/app/page.tsx#L27C8-L28

@pavlovtech
Copy link

Related issue: #43548

@juliendelort
Copy link

hey @juliendelort , by default suspense do not show the fallback everytime when used on searchParams, i added a key to Suspense and that's what makes it show everytime : https://github.com/Fredkiss3/vercel-streaming-bug/blob/4f6a356f67fd0a034d9f148e8588dcb0319e0e45/app/page.tsx#L27C8-L28

@Fredkiss3 Curious if that's the intended way and if it's documented somewhere? The closest thing I could find was this in the React docs, but they mention adding the key to the child of Suspense, not Suspense itself.

@Fredkiss3
Copy link
Contributor Author

It is basically the same, passing a key to Suspense tells react to consider the component as new one, resetting it.

i don't know if next uses key on pages, but it seems to ignore the fallback for the same page. I think that it doesn't, because if the page is using queryString in the key of the page, the fallback would show by default.

the key thing is one trick i got from dan abramov on twitter because this one was bugging me, i wanted to show the fallback everytime on a search page when the params where updating.

@leerob
Copy link
Member

leerob commented Jul 17, 2023

I realized I didn't follow up here from my original message – there was some conversation with @matt-kruse on Twitter. He shared his solution here.

So far the root causes we've seen are either due to the network or from Safari. For the network, if you are behind a proxy, some can interfere with streaming. Please verify you're seeing the same behavior across multiple networks. Secondly, please verify if you're seeing an issue across multiple browsers. Safari is known to have issues streaming when the payload is extremely small (like a hello world app) but not as it's larger. I can't find the exact bug to link back to right now, but we've seen this one commonly reported but building the most basic streaming examples (due to the small size of the payload).

Please give this a shot and we'll keep investigating on our side as well too. Any additional information helps!

@Fredkiss3
Copy link
Contributor Author

Fredkiss3 commented Jul 17, 2023

@leerob
Tested on my end on three networks : my workplace, my home and my mobile data outside & three browsers : Firefox, Safari & Chrome and the issue still persist, on safari, wether i test from safari or other browsers, it always streams for other providers (railway & cloudfare), vercel is the only one when it streams sometimes (the fallback is shown), and it sometimes it doesn't on the 3 browsers and networks.

If it was a proxy issue, i think i would have a different behavior with at least one of the networks or one of the other providers (i think). If it was safari, it would behave differently but the behavior stays consistent between browsers and networks.

What is weird is that when i inspect the network tab on vercel vs cloudfare (for ex), i see the same timeline but visually i have two different results (the first without fallback & the second with a fallback) :

Vercel

image

Cloudfare

image

It may be a client side problem ? Maybe vercel compiles next a little differently ? 🤔

@leerob
Copy link
Member

leerob commented Jul 17, 2023

Related thread discussing the browser issue (which they're seeing on multiple platforms): sveltejs/kit#9154 (comment)

@Fredkiss3
Copy link
Contributor Author

@leerob tested with another phone of a friend out of the bounds of my network (literally the other side of the world), the issue still stands... only on vercel.

@feedthejim
Copy link
Contributor

Hey we found the issue I think so we're rolling out a fix on production soon enough. Thanks for reporting and digging @Fredkiss3, super helpful.

@leerob
Copy link
Member

leerob commented Jul 19, 2023

This fix has been deployed! Thank you all for the helpful information and reproductions.

@leerob leerob closed this as completed Jul 19, 2023
@matt-kruse
Copy link

Just for clarity - this fix is to Vercel, not to NextJS? I'm still seeing the problem on my Vercel-hosted NextJS app, so I suspect my issue is still that I'm running through an enterprise proxy?

@Fredkiss3
Copy link
Contributor Author

Thanks @leerob @feedthejim i have tested and the issue is fixed on my end.

With the original link.

@YoussefKababe
Copy link

Wow happy to hear the issue was finally fixed. My app now works as it's supposed to! ❤️ 🎉

@avivm
Copy link

avivm commented Aug 13, 2023

I'm still experiencing the issue with nested Suspense in Vercel (Working correctly on local).
The parent Suspense shows fallback correctly but it keeps showing even after it is loaded instead of showing the child Suspense fallback. The child Suspense is not displayed throughout the entire process and the page is loaded only with the parent Suspense.
To make it even better it does work sporadically and showing the child Suspense fallback.

@mrjasonroy
Copy link

This is happening to me in production now with nested suspense as well. Blocking the content download. Nice waterfall locally but issues on Vercel.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 1, 2023

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot added the locked label Sep 1, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 1, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template. locked Navigation Related to Next.js linking (e.g., <Link>) and navigation. Pages Router Related to Pages Router.
Projects
None yet
Development

No branches or pull requests