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

React 17 + 18 support #718

Closed
apepper opened this issue Mar 10, 2021 · 41 comments
Closed

React 17 + 18 support #718

apepper opened this issue Mar 10, 2021 · 41 comments
Assignees

Comments

@apepper
Copy link

apepper commented Mar 10, 2021

Currently @loadable/component only supports react 16 is supported:

"react": "^16.12.0",
"react-dom": "^16.12.0",

It would be great, if it would also support React 17 and the latest React 18.

@open-collective-bot
Copy link

Hey @apepper 👋,
Thank you for opening an issue. We'll get back to you as soon as we can.
Please, consider supporting us on Open Collective. We give a special attention to issues opened by backers.
If you use Loadable at work, you can also ask your company to sponsor us ❤️.

@theKashey theKashey self-assigned this Mar 18, 2021
@stale
Copy link

stale bot commented Jun 2, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jun 2, 2021
@apepper
Copy link
Author

apepper commented Jun 3, 2021

This is not stale. React 17 is still not supported:

"react": "^16.12.0",
"react-dom": "^16.12.0",

@stale stale bot removed the wontfix label Jun 3, 2021
@partoneplay
Copy link

I use react@17.0.2 and @loadable/component@5.15.0. They work well.

@azangru
Copy link

azangru commented Jul 11, 2021

They work, but it shows a dependency conflict when installing packages with npm 7:

image

Please fix this 🙏

@stale
Copy link

stale bot commented Sep 10, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Sep 10, 2021
@theKashey theKashey removed the wontfix label Sep 11, 2021
@IPRIT
Copy link

IPRIT commented Nov 5, 2021

Still relevant

@stale
Copy link

stale bot commented Jan 9, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jan 9, 2022
@stale
Copy link

stale bot commented Apr 16, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Apr 16, 2022
@IPRIT
Copy link

IPRIT commented Apr 17, 2022

1️⃣7️⃣

@stale stale bot removed the wontfix label Apr 17, 2022
@theKashey
Copy link
Collaborator

1️⃣8️⃣

@apepper apepper changed the title React 17 support React 17 + 18 support Apr 19, 2022
@mike-parkhomenko
Copy link

Hey! Is it possible to let us know approximately date for the next release with React 17,18 support?

Thanks)

@abhisharkjangir
Copy link

Is it supports react v18? I'm getting below error with

  • "react": "^18.1.0"
  • "react-dom": "^18.1.0"
  • webpack": "^5.73.0"
  • "@loadable/babel-plugin": "^5.13.2",
  • "@loadable/component": "^5.15.2",
  • "@loadable/server": "^5.15.2",
  • "@loadable/webpack-plugin": "^5.15.2",

image

@reverofevil
Copy link

reverofevil commented Jun 21, 2022

@abhisharkjangir No, it doesn't. The library is mostly dead for the last 2 years, except for a few fixes by @theKashey.

@azangru
Copy link

azangru commented Jun 22, 2022

Now that the React team has stopped recommending loadable-components in their docs, does anyone know what the official blessed setup is? With React.lazy, webpack, server-side rendering, and all?

image

@reverofevil
Copy link

React 18 is a frontend library, it can't collect a list of dynamic imports that were awaited for during SSR. You can't do it with loadable components anymore, because it's incompatible. You can't do it with Vite SSR in dev mode, because it uses ESM and you can't hook calls to require there. I don't think there is any solution at the moment that actually works and might be used in production.

@azangru
Copy link

azangru commented Jun 22, 2022

I'll just leave Dan's code sandbox here, from a comment where he said that React.lazy "just works" now. Perhaps this is what the recommended way of doing this now is.

@theKashey
Copy link
Collaborator

There is no recommended way of doing this and the majority of libraries(or react itself) are not working one way or another due to different reasons.

@vaukalak
Copy link

@abhisharkjangir I've created an example of usign loadable-components with react 18. It might be, that you were facing the same hydration issue before, due to differences in your server and client generated HTML. However now, with react 18 this actually creates an error, rather than just logging the warning.

@abhisharkjangir
Copy link

@vaukalak Thanks, I'll try if it works for me or not.

@fivethreeo
Copy link
Contributor

React 18 with Suspense would be better if chunkextractor could have a reset method. Then we could use a custom writable in renderToPipeableStream that wrote the discovered components script tags as we render.

But loadableReady in the client cannot be used anymore so maybe write some script tags that say which modules will be loaded from those async script tags so we don’t try to refetch those during hydration.

If I understand all this correctly.

reactwg/react-18#114

https://github.com/brillout/react-streaming#injecttostream

@santicalvo
Copy link

santicalvo commented Nov 14, 2022

Hello, I see there is a next release tag on this issue.

Is there a roadmap or a release date scheduled? Any branch for development?

Thanks a lot for this library!

@fivethreeo
Copy link
Contributor

So decided to not use

https://github.com/brillout/react-streaming#injecttostream

Instead I did this

  let didError = false;
  let shellReady = false;

  class LoadableWritable extends Writable {
    constructor(writable) {
      super();
      this._writable = writable;
    }

    _write(chunk, encoding, callback) {
      // This should pick up any new link tags that hasn't been previously
      // written to this stream.
      if (shellReady) {
      }
      // Finally write whatever React tried to write.

      this._writable.write(chunk, encoding, callback);
    }

    end() {
      this._writable.end()
    }

    flush() {
      if (typeof this._writable.flush === 'function') {
        this._writable.flush();
      }
    }
  }

  const writeable = new LoadableWritable(res)

  const stream = renderToPipeableStream(<Html assets={{}}><App /></Html>,
    {
      onShellReady() {
        // The content above all Suspense boundaries is ready.
        // If something errored before we started streaming, we set the error code appropriately.
        res.statusCode = didError ? 500 : 200;
        res.setHeader('Content-type', 'text/html');
        shellReady = true;

        stream.pipe(writeable);

      })

https://github.com/fivethreeo/loadable-components-react-18

Will try adding loadabe-components soon

Clone and run

pnpm i
pnpm start

@fivethreeo
Copy link
Contributor

Tried adding loadable components with streaming react and suspense. Did not work.

@fivethreeo
Copy link
Contributor

fivethreeo commented Nov 17, 2022

@dglozic
Copy link

dglozic commented Jan 26, 2023

Any outlook for React 18 support in the near future?

@theKashey
Copy link
Collaborator

There is "real" React 18 support in works - #923, but I don't see any reason not to update package dependencies right away...

@dglozic
Copy link

dglozic commented Jan 27, 2023

I agree - people can upgrade to 18 and get the current code to work, while deferring the use of renderToPipeableStream and suspense until it is supported by loadable components. Actually, no, they can (and must) use it as renderToNodeStream is buffered in 18, but we can continue to render the App portion using renderToString while collecting loadables in SSR until full support is available.

@theKashey
Copy link
Collaborator

v5.15.3 has react dependency version changed

  • from
    • "react": ">=16.3.0", which should work
  • to
    • "react": "^16.3.0 || ^17.0.0 || ^18.0.0", which definitely works and more common in the ecosystem

@TwisterMc
Copy link

Did this happen? I don't see a v 5.15.3 in the releases and v5.16.0 says "react": "^16.12.0"

@chidev
Copy link

chidev commented Aug 29, 2023

I agree - people can upgrade to 18 and get the current code to work, while deferring the use of renderToPipeableStream and suspense until it is supported by loadable components. Actually, no, they can (and must) use it as renderToNodeStream is buffered in 18, but we can continue to render the App portion using renderToString while collecting loadables in SSR until full support is available.

Any idea how we can get React 18 and Loadable to work correctly? Just some general steps / direction would be greatly appreciated.

@dglozic
Copy link

dglozic commented Aug 29, 2023

We are using Loadable just fine in React 18, what's the issue? We (IBM) are currently using the latest loadable-components with React 18.2 and Loadable works fine (we are doing as explained above - rendering the App porting using renderToString, collecting loadables in SSR and then rendering the envelope using renderToPipeableStream).

@azangru
Copy link

azangru commented Aug 30, 2023

We (IBM) are currently using the latest loadable-components with React 18.2 and Loadable works fine (we are doing as explained above - rendering the App porting using renderToString, collecting loadables in SSR and then rendering the envelope using renderToPipeableStream).

Any reason why you prefer this over React.lazy?

@dglozic
Copy link

dglozic commented Aug 30, 2023

SSR. We use Loadable since React16 and needed it for server side rendering. For the client side, Lazy is fine. Obviously React has this new approach for SSR in 18 with Suspense and Server Only components but this is still early and they apparently let the likes of Next.js and Remix to take the lead and define what SSR should look like with Suspense. We are waiting for that dust to settle and continuing to use Loadable as explained above.

@azangru
Copy link

azangru commented Aug 30, 2023

I just wanted to put it out there that React.lazy works fine with SSR without any requirement for Next, or server components, or anything like that. I'm using it with my custom (i.e. non-next) SSR setup. There's a minimal demo linked to in a comment above.

@theKashey
Copy link
Collaborator

Unfortunately using Lazy, or better to say - relying on Suspense does not work in many case.
The problem is - any update to the context above Suspense will trigger it into loading mode, so you will lose not yet hydrated content - facebook/react#22692

That's it - your app is expected to be "dead" until hydration is complete and loadableReady is a way to understand when it's the right time to move forward.

This is not a "code splitting" library, this is "code tracking" library. That something Lazy does not do

@salihovdr
Copy link

We are using Loadable just fine in React 18, what's the issue? We (IBM) are currently using the latest loadable-components with React 18.2 and Loadable works fine (we are doing as explained above - rendering the App porting using renderToString, collecting loadables in SSR and then rendering the envelope using renderToPipeableStream).

Can you share a basic example in code? Really curious about this part: "rendering the App porting using renderToString, collecting loadables in SSR and then rendering the envelope using renderToPipeableStream).
"

@dglozic
Copy link

dglozic commented Mar 1, 2024

Unfortunately there is too much code in too many places to distill into a simple example. Let me try in words:

  1. We use SSR to render the server-side state of the root React element into a string buffer.
  2. We then render the overall page with the common header, static parts etc., using the computed stats from the first render pass (CSS, JS etc.). This render is using pipeable stream.
  3. When we do (2), we keep the pipe open so that API calls we made before (1) can complete.
  4. As the API calls are completing, they append the result of the call as JSON elements to the stream.
  5. On the client, as JSON elements with API call results arrive, we aggressively grab them and render the components that need them.
  6. Pipe closes.

Visually, it looks great - normally the first render is in under 200ms, and entire page is done rendering in under 500ms, even with multiple API calls done to fetch necessary metadata.

While we are watching Server Only Components and Suspense story evolve, we don't want to commit to Next.js or Remix to get them.

@salihovdr
Copy link

@dglozic is that an internal company solution or was is based on an existing blueprint? I've been looking into using renderToPipeableStream without next.js and Google led me to this thread.

@dglozic
Copy link

dglozic commented Mar 1, 2024

It is internal, yes. But it is not hard to reproduce. It is also kind of interim because some proposals to support stats with streaming didn't yet make it into loadable-components (hence the initial render to a buffer to get the stats computed the old way). I keep hoping that @fivethreeo has put together would get merged :-).

@salihovdr
Copy link

Gonna take a look at that example. Thank you!

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