Skip to content

renderToPipeableStream in server.js Does Not Wait for Async Content Inside Suspense #40

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

Open
welkinwong opened this issue Apr 23, 2025 · 4 comments

Comments

@welkinwong
Copy link

The renderToString method in server.js converts the stream returned by renderToPipeableStream into a string. However, during testing, it was observed that onAllReady is triggered and toString() is called before the stream fully completes, meaning it does not wait for asynchronous content inside Suspense boundaries.

Issue:

  • onAllReady fires once the initial shell (non-Suspense content) is rendered, but does not wait for Suspense-bound async components to resolve.
  • This can lead to incomplete HTML if toString() is called prematurely.
=> Meteor server restarted at: http://localhost:3000/
I20250423-16:02:43.723(8)? onShellReady
I20250423-16:02:43.723(8)? --- Chunk 1 ---
I20250423-16:02:43.724(8)? <div class="max-w-3xl min-h-screen mx-auto sm:pt-10"><h1 class="text-center text-5xl font-extrabold">Meteor Community Packages</h1><h1 class="text-center text-8xl font-extrabold">SSR Demo</h1>ddd<!--$?--><template id="B:0"></template><div>Loading...</div><!--/$--></div><script>window.__staticRouterHydrationData = JSON.parse("{\"loaderData\":{\"0\":null},\"actionData\":null,\"errors\":null}");</script>
I20250423-16:02:43.724(8)? --- Chunk 2 ---
I20250423-16:02:43.724(8)? <div hidden id="S:0"><div class="bg-white shadow sm:rounded-lg mb-4"><div class="px-4 py-5 sm:p-6"><div class="sm:flex sm:items-start sm:justify-between"><div><div class="flex items-center"><h3 class="text-3xl text-gray-900 font-bold">Welcome to the React SSR Demo!</h3><div><svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 400 400"><g fill="#DE4F4F"><path d="
I20250423-16:02:43.724(8)? --- Chunk 3 ---
I20250423-16:02:43.724(8)? M286.575 306.886L44.755 49.922l256.962 241.82c4.312 4.056 4.518 10.837.46 15.146-4.053 4.31-10.832 4.518-15.144.46-.15-.14-.318-.31-.458-.462M251.032 325.01L68.692 127.528 266.177 309.87c4.35 4.013 4.618 10.794.604 15.144-4.018 4.35-10.794 4.617-15.146.604-.2-.19-.413-.406-.602-.607M214.083 325.542L92.907 194.272 224.18 315.446c2.898 2.676 3.077 7.197.402 10.098-2.677 2.896-7.195 3.082-10.097.402-.136-.125-.277-.272-.402-.405M315.612 234.685L189.102 98.078 325.71 224.585c2.896 2.684 3.067 7.203.387 10.1-2.682 2.895-7.2 3.066-10.098.387-.13-.123-.268-.258-.388-.387M304.697 272.93L121.567 74.655l198.274 183.13c4.35 4.017 4.62 10.796.605 15.144-4.017 4.352-10.797 4.617-15.146.604-.205-.19-.418-.404-.603-.605M176.31 314.783l-57.647-62.695 62.692 57.65c1.453 1.334 1.547 3.596.215 5.045-1.338 1.453-3.598 1.55-5.05.215-.072-.07-.144-.143-.21-.215M311.093 189.297l-57.65-62.694 62.696 57.646c1.45 1.335 1.546 3.597.21 5.048-1.335 1.45-3.595 1.547-5.05.21-.07-.065-.143-.143-.207-.21
I20250423-16:02:43.724(8)? --- Chunk 4 ---
I20250423-16:02:43.724(8)? "></path></g></svg></div></div><div class="mt-2 max-w-xl text-gray-500 text-lg"><p>You&#x27;ve pressed the button <b>0</b> times.</p></div></div><div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center"><button type="button" class="inline-flex items-center px-4 py-2 border border-transparent shadow-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 text-lg">Click Me</button></div></div></div></div><template id="P:1"></template></div>
I20250423-16:02:43.728(8)? onAllReady <div class="max-w-3xl min-h-screen mx-auto sm:pt-10"><h1 class="text-center text-5xl font-extrabold">Meteor Community Packages</h1><h1 class="text-center text-8xl font-extrabold">SSR Demo</h1>ddd<!--$?--><template id="B:0"></template><div>Loading...</div><!--/$--></div><script>window.__staticRouterHydrationData = JSON.parse("{\"loaderData\":{\"0\":null},\"actionData\":null,\"errors\":null}");</script><div hidden id="S:0"><div class="bg-white shadow sm:rounded-lg mb-4"><div class="px-4 py-5 sm:p-6"><div class="sm:flex sm:items-start sm:justify-between"><div><div class="flex items-center"><h3 class="text-3xl text-gray-900 font-bold">Welcome to the React SSR Demo!</h3><div><svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 400 400"><g fill="#DE4F4F"><path d="M286.575 306.886L44.755 49.922l256.962 241.82c4.312 4.056 4.518 10.837.46 15.146-4.053 4.31-10.832 4.518-15.144.46-.15-.14-.318-.31-.458-.462M251.032 325.01L68.692 127.528 266.177 309.87c4.35 4.013 4.618 10.794.604 15.144-4.018 4.35-10.794 4.617-15.146.604-.2-.19-.413-.406-.602-.607M214.083 325.542L92.907 194.272 224.18 315.446c2.898 2.676 3.077 7.197.402 10.098-2.677 2.896-7.195 3.082-10.097.402-.136-.125-.277-.272-.402-.405M315.612 234.685L189.102 98.078 325.71 224.585c2.896 2.684 3.067 7.203.387 10.1-2.682 2.895-7.2 3.066-10.098.387-.13-.123-.268-.258-.388-.387M304.697 272.93L121.567 74.655l198.274 183.13c4.35 4.017 4.62 10.796.605 15.144-4.017 4.352-10.797 4.617-15.146.604-.205-.19-.418-.404-.603-.605M176.31 314.783l-57.647-62.695 62.692 57.65c1.453 1.334 1.547 3.596.215 5.045-1.338 1.453-3.598 1.55-5.05.215-.072-.07-.144-.143-.21-.215M311.093 189.297l-57.65-62.694 62.696 57.646c1.45 1.335 1.546 3.597.21 5.048-1.335 1.45-3.595 1.547-5.05.21-.07-.065-.143-.143-.207-.21"></path></g></svg></div></div><div class="mt-2 max-w-xl text-gray-500 text-lg"><p>You&#x27;ve pressed the button <b>0</b> times.</p></div></div><div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center"><button type="button" class="inline-flex items-center px-4 py-2 border border-transparent shadow-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 text-lg">Click Me</button></div></div></div></div><template id="P:1"></template></div>
I20250423-16:02:43.728(8)? --- Chunk 5 ---
I20250423-16:02:43.728(8)? <div hidden id="S:1">asdf</div><script>$RS=function(a,b){a=document.getElementById(a);b=document.getElementById(b);for(a.parentNode.removeChild(a);a.firstChild;)b.parentNode.insertBefore(a.firstChild,b);b.parentNode.removeChild(b)};$RS("S:1","P:1")</script><script>$RC=function(b,c,e){c=document.getElementById(c);c.parentNode.removeChild(c);var a=document.getElementById(b);if(a){b=a.previousSibling;if(e)b.data="$!",a.setAttribute("data-dgst",e);else{e=b.parentNode;a=b.nextSibling;var f=0;do{if(a&&8===a.nodeType){var d=a.data;if("/$"===d)if(0===f)break;else f--;else"$"!==d&&"$?"!==d&&"$!"!==d||f++}d=a.nextSibling;e.removeChild(a);a=d}while(a);for(;c.firstChild;)e.insertBefore(c.firstChild,a);b.data="$"}b._reactRetry&&b._reactRetry()}};$RC("B:0","S:0")</script>
I20250423-16:02:43.728(8)? --- Stream ended ---

Reproduction Steps:

In this project: https://github.com/copleykj/react-router-ssr-demo
upgrade react-meteor-data to [email protected], and the issue can be observed.

PS: I used a loggerStream to log chunk information for debugging.

let chunkCount = 0;

const loggerStream = new Transform({
  transform(chunk, encoding, callback) {
    chunkCount++;
    console.log(`--- Chunk ${chunkCount} ---`);
    console.log(chunk.toString());
    this.push(chunk);
    callback();
  },
  flush(callback) {
    console.log('--- Stream ended ---');
    callback();
  }
});

In the forums, users reported a failure in [email protected]
https://forums.meteor.com/t/communitypackages-react-router-ssr-v6-beta-release/63418/3

Copy link

Thank you for submitting this issue!

We, the Members of Meteor Community Packages take every issue seriously.
Our goal is to provide long-term lifecycles for packages and keep up
with the newest changes in Meteor and the overall NodeJs/JavaScript ecosystem.

However, we contribute to these packages mostly in our free time.
Therefore, we can't guarantee you issues to be solved within certain time.

If you think this issue is trivial to solve, don't hesitate to submit
a pull request, too! We will accompany you in the process with reviews and hints
on how to get development set up.

Please also consider sponsoring the maintainers of the package.
If you don't know who is currently maintaining this package, just leave a comment
and we'll let you know

@copleykj
Copy link
Member

I think the issue you are seeing is that the useSubscribe (suspendable) hook in the react-meteor-data package does not call Meteor.subscribe on the server and is rather a noop in the case of server rendering. This package now provides a useSubscribeSuspense hook that can be imported in used in place of the useSubscribe hook provided by the react-meteor-data package. Give it a try and see if that fixes your issue.

@welkinwong
Copy link
Author

@copleykj I tried it, but it still doesn’t work. Here’s a reproducible fork link (https://github.com/welkinwong/react-router-ssr-demo-issue), just upgraded to [email protected].

@copleykj
Copy link
Member

Thanks, I'll have a look.

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

No branches or pull requests

2 participants