SSR with Meteor.callAsync

Looking at this further, there is a need to extend/create a new boilerplate that will support renderToPipeableStream of React 18

Here is a quick reproduction where SSR does not work:

  • still using Meteor.call()
  • Meteor 2.14
  • Reach 18.2
  • React Router 6.21
  • using Suspense and lazy
  • using renderToString()

The goal is to support the following through SSR and code-splitting:

  • loading performance
  • better UX
  • SEO

It looks like it works because the app works after hydration. Disabling javascript in the browser shows the real status of the SSR:

  1. Suspense and lazy did not work in SSR when not yet cached by the server
  2. renderToString() is not meant to wait for data

Screenshot from 2023-12-22 20-05-17

Potential solution:

  1. Make data fetching Suspense-enabled, i.e., throw promises when data is not yet ready
  2. Support renderToPipeableStream() by forking the following Meteor packages:
  • server-render
  • boilerplate-generator
  • webapp

I will post an update here if this will work. Do you have other ideas/comments/feedback?

3 Likes

While studying renderToPipeableStream(), it becomes clear that React 18 expects to start hydration on document (therefore the entire HTML document) instead of an element inside <body>.

This means that the boilerplate template for React 18 SSR must also be JSX.

Good News!

SSR works with the following:

  1. Meteor 2.14
    • Using Meteor.callAsync()
  2. React Router 6.21
  3. React 18.3.0-canary-c5b937576-20231219

The example in the above branch has a component and data loaded using Suspense and nested lazy loaded components.

Screenshot from 2023-12-24 02-53-23

Caveats:

The use() hook simplifies everything with Meteor.callAsync() and Suspense.

const { links } = use(Meteor.callAsync('getLinks'));

To Do:
Since renderToNodeStream() is deprecated, there is still a need to support renderToPipeableStream() moving forward. There are two important things to do to make this possible:

  1. Support a JSX boilerplate-generator template because hydration now happens on document instead of an HTML element. This requires allowing a custom template to generate the HTML output. Either Meteor adds a custom template for React or allows the developer to add one.
  2. Allow access to the response parameter accessible by renderToPipeableStream()

Ideally, these features will be available through server-render package.

2 Likes

So, I’ve just proven myself wrong. With the solution above, it’s possible to even make this work with class components with data fetching happening in the constructor() when defining the component state variables

Any updates to this??

In other words, how do you make SSR work with Meteor 3?

have you tried this one: Communitypackages:react-router-ssr v6 beta release - #3 by copleykj

I have previously used it, but there was an issue for my own case that I had struggled, so I implemented my own.

Here is my initialization at server startup:

Here is all the components I use in SSR:

@minhna My concern is not being able to do the Meteor.callAsync, in the referenced ssr components file. I tried, not working…

This has been the single blocker for me preventing to upgrade to Meteor 3.

Any advice is welcome, thanks!

The following should work:

  • Meteor 3
  • React 18 canary for the use() hook

The use() hook allows you to await the Meteor.callAsync method and suspend the rendering

1 Like

Great! Thanks for this. Will try soonest and update here. Meanwhile, if you can share a piece of code as example, it would be awesome.

I was trying to upgrade my example above to Meteor 3 but was met with package conflicts. I don’t have time to figure out the issue for now so I don’t have an example to share.

We are also in the middle of upgrading our SSR code to Meteor 3 (on hold due to new business requirements we have to prioritize). We are currently moving data fetching as a parent of SSR components to allow suspending the entire component with use()

Please share if you have something to show. I’ll do the same thing once I get the opportunity

2 Likes