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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NoSsr] Investigate better alternatives in React 18 #26763

Open
eps1lon opened this issue Jun 15, 2021 · 6 comments
Open

[NoSsr] Investigate better alternatives in React 18 #26763

eps1lon opened this issue Jun 15, 2021 · 6 comments

Comments

@eps1lon
Copy link
Member

eps1lon commented Jun 15, 2021

Summary 馃挕

Check each use case with React 18 in mind. Our docs are probably a good start.

Examples 馃寛

<NoSsr fallback="loading">
  <Suspense fallback="loading">
    <SomeLazyComponent />
  </Suspense>
</NoSsr>

can be written without NoSsr alltogether.

Motivation 馃敠

NoSsr only renders its children when an effect ran. This leads to cascading updates which is especially problematic for the default case where defer={false} and we use layout effects.

The reason we have NoSsr is to not render components that don't do anything before hydration. In React 18 we now have access to Suspense which enables streaming rendering and selective hydration which should cover most use cases while also improving existing scenarios (e.g. prioritizing hydration).

@oliviertassinari
Copy link
Member

oliviertassinari commented Jul 24, 2021

The reason we have NoSsr

To extend on the different product use cases we have had so far for the NoSsr component, I have seen:

  1. Speed up server-side rendering (reduce CPU load on the server), e.g. DDoS, need to skip the whole phase
  2. Don't render broken third-party component that uses the browser API (likely a less frequent issue nowadays), e.g. styled-components not configured in v4, react-admin
  3. Speed up to interactive for the most important parts of the user / make it feel more responsive. How? By splitting hydration into two steps. e.g. demo's toolbar, NProgressBar.
  4. Hide elements that can't be cached in the SSR output, e.g. user login information.
  5. Dodge hydration inconsistencies, e.g. Intl.NumberFormat using different locale datasets between client and server

Suspense seems to cover 3.

@eps1lon
Copy link
Member Author

eps1lon commented Jul 25, 2021

Suspsense covers 1, 3, 4. 2 does not need an extra component. 5 is an issue with the SSR setup.

Speed up server-side rendering (reduce CPU load on the server), e.g. DDoS, need to skip the whole phase

Not sure what the type of attack has to do with it. If you're DDoSed no amount of NoSSR will help. The attack preventation should not happen at the render layer.

@oliviertassinari
Copy link
Member

oliviertassinari commented Jul 25, 2021

  1. Do you mean that the solution should be to create its own component?
  2. I guess it depends on the approach. When using intl.datetimeformat, the dataset https://nodejs.org/api/intl.html#intl_internationalization_support is evolving. From what I understand, it's not guaranteed that the browser uses the same version of the dataset as the client. But I guess developers can consider these hydration mismatches and hedge cases, it a small flicker. Or developers can use a polyfill with predictable behavior, or they can render an empty placeholder on the server-side.

Not sure what the type of attack has to do with it. If you're DDoSed no amount of NoSSR will help. The attack preventation should not happen at the render layer.

  1. It might be a hedge case to ignore. In the past, I had wrapped the whole server-side output in Next.js with a NoSsr, wired it to a value in Redis, to be able to completely turn off server-side rendering in case we had a CPU load issue (not enough resources/too much traffic).

So, the path we might be able to take is to deprecate NoSsr?

@eps1lon
Copy link
Member Author

eps1lon commented Jul 26, 2021

So, the path we might be able to take is to deprecate NoSsr?

We'll want to wait for a stable release of 18 anyway. And then we can go through each use case of NoSsr and see if we can replace it.

to be able to completely turn off server-side rendering in case we had a CPU load issue (not enough resources/too much traffic).

Yeah, this should happen at another layer. It's not even clear this works since you would have to signal to the client side bundle that the rendered tree changes. Otherwise you're hydrating differnt trees which generally has undefined behavior. If it does work then you're degrading client side rendering as well. You should just send the HTML skeleton and then call ReactDOM.render on the client. Instead of calling sending the ReactDOMServer.render(null) and hydrating that tree.

@bryanltobing
Copy link

bryanltobing commented Jul 13, 2022

I'm currently need suspense at my top-level component. In my case, it's next.js apps

<Suspense fallback={<div>Loadingss...</div>}>
  <DefaultLayout>
    <Component {...pageProps} />
  </DefaultLayout>
</Suspense>

but in order for this to work, I need to wrap it with <NoSsr/> component

<NoSsr fallback="Loading">
 <Suspense fallback="Loading">
   <...Rest/>
 </Suspense>
</NoSsr>

Is this the correct approach for now, in order to make the suspense of React 18 work?

I'm afraid this might slow down the TTI since we pass fallback two times in there. This is just my guess tho

@eps1lon
Copy link
Member Author

eps1lon commented Jul 13, 2022

Is this the correct approach for now, in order to make the suspense of React 18 work?

In React 18 you can use <Suspense /> on the server. It's one of the reasons why I wanted to remove this component since it most likely results in degraded UX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants