honojs / middleware

monorepo for Hono third-party middleware/helpers/wrappers
https://hono.dev
422 stars 145 forks source link

[@hono/react-renderer] `renderToReadableStream` is not a function #627

Closed tsuki-lab closed 2 months ago

tsuki-lab commented 3 months ago

When using { stream: true }, if renderToReadableStream did not exist, I got the error as shown in the title.

Case

export const renderer = reactRenderer(
  ({ children }) => {
    return (
      <html>
        <body>
          <div>{children}</div>
        </body>
      </html>
    );
  },
  { stream: true }
);

Thanks again for all your great development.

yusukebe commented 3 months ago

Hi @tsuki-lab

Thank you for the issue!

@yoshikouki Can you take a look?

yoshikouki commented 3 months ago

Hi @tsuki-lab

Just to confirm, were you encountering this error on Bun v1.1.x? And is this the error you encountered?

4 | var RequestContext = React.createContext(null);
5 | var createRenderer = (c, Layout, component, options) => async (children, props) => {
6 |   const node = component ? component({ children, Layout, c, ...props }) : children;
7 |   if (options?.stream) {
8 |     const { renderToReadableStream } = await import("react-dom/server");
9 |     const stream = await renderToReadableStream(
                             ^
TypeError: renderToReadableStream is not a function. (In 'renderToReadableStream(React.createElement(RequestContext.Provider, { value: c }, node), options.readableStreamOptions)', 'renderToReadableStream' is undefined)
      at /Users/yoshikouki/src/github.com/yoshikouki/hono-vite/bun/node_modules/@hono/react-renderer/dist/index.js:9:26

If so, this appears to be an issue with Bun v1.1.x rather than @hono/react-renderer. This issue is reported here: https://github.com/oven-sh/bun/issues/9949

The workaround mentioned in the issue suggests either importing renderToReadableStream from 'react-dom/server.browser' or using React 19 RC. However, changing the import in our library might affect other environments outside of Bun, so it’s not a straightforward decision.

Here are some immediate solutions:

  1. Install React 19 RC: bun add react@canary react-dom@canary
  2. Downgrade Bun to v1.0.x
  3. Clone our library locally and change line 35 in react-renderer.ts to: const { renderToReadableStream } = await import('react-dom/server.browser') https://github.com/honojs/middleware/blob/61cd9b6a57c6ac9957c00260a23e0a23ebbae144/packages/react-renderer/src/react-renderer.ts#L35

If your environment is not Bun v1.1.x, please provide more details about the error.

Thank you for reporting this issue.

tsuki-lab commented 2 months ago

Hi @yoshikouki

Thanks for the quick reply. I was indeed using 1.1.18 of bun.

I tried the following solution as a test, but the result was the same.

  1. Install React 19 RC: bun add react@canary react-dom@canary
  2. Downgrade Bun to v1.0.x

Also, using a package manager such as npm other than bun did not change the result.


Just in case... I have created a reproducible environment that inspired me to create this issue. I would be happy if it would be of any help. https://github.com/tsuki-lab/hono-middleware-issue-627

Perhaps it is true that the bun version is 1.1.X.

yoshikouki commented 2 months ago

@tsuki-lab Thank you for providing the reproducible environment! It’s very helpful.

It looks like the version of React is still 18: https://github.com/tsuki-lab/hono-middleware-issue-627/blob/fb6af3b0f4ac5d81a169841f92faa21333ad1491/package.json#L13-L14

If bun add react@canary react-dom@canary doesn’t update the version, try removing React and ReactDOM from your package.json first and then run the command again.

It should look like this: https://github.com/yoshikouki/hono-vite/blob/5c6ad79c273581733784640e3f8d9849f8f4b454/bun/package.json#L9-L10

For handling with Bun v1.0.x (just to bypass the error, not recommended for production), ensure that Bun v1.0.x is being used. It works fine in my environment:

$ bun -v; PORT=8888 bun --cwd=bun dev
1.0.36
$ bun run --hot src/index.tsx
Started server http://localhost:8888
rendered /

A working example can be found here (using v1.0.36): https://github.com/yoshikouki/hono-vite/tree/e8aa6fe28a2da999988f06c7553961e2eb956374

Thanks again for your cooperation.

yoshikouki commented 2 months ago

Also, using a package manager such as npm other than bun did not change the result.

For additional context, when you run this code with npm instead of Bun, the runtime will be Node.js. In this case, you will encounter a different issue specific to Node.js, leading to a similar error.

The renderToReadableStream function from react-dom/server cannot be used with Node.js, and thus @hono/react-renderer, which depends on it, will have the same limitation (it works with Edge environments like Cloudflare Workers or Bun).

Please refer to this comment for more details: https://github.com/honojs/middleware/pull/419#issuecomment-2002009785

tsuki-lab commented 2 months ago

@yoshikouki Thank you very much.

I tried updating to react@canary and react-dom@canary to verify the behavior, but the result did not change.

After running bun run --hot src/index.tsx from the attached repository, we confirmed that it works correctly in the environment updated to react@canary and react-dom@canary.

We additionally proceeded to identify the cause of the reproduction and found that the combination with @hono/vite-dev-server was the cause this time.

The renderToReadableStream error appears in the environment with @hono/vite-dev-server.

https://github.com/tsuki-lab/hono-middleware-issue-627/blob/c67cb3bb3fc42d94a0621cdf5eef0887f297fc42/package.json#L5-L6

JoshStwrt commented 2 months ago

I'm also experiencing a similar issue, but after cloning and running the app from this repository. The only changes made were updating the packages to the latest stable versions.

[vite] Error when evaluating SSR module /node_modules/.pnpm/@remix-run+dev@2.10.2_@remix-run+react@2.10.2_react-dom@18.3.1_react@18.3.1__react@18.3.1_typ_ghgf4g5oh3h4vmpn6yk6bbyose/node_modules/@remix-run/dev/dist/config/defaults/entry.server.cloudflare.tsx: failed to import "react-dom/server"
|- SyntaxError: [vite] Named export 'renderToReadableStream' not found. The requested module 'react-dom/server' is a CommonJS module, which may not support all module.exports as named exports.

Using Node 22.3.0 and PNPM 9.5.0.

yoshikouki commented 2 months ago

Thank you for your verification and report! I also encountered the same error and suspect it is because @hono/vite-dev-server internally uses @hono/node-server.

By modifying part of node_modules/@hono/react-renderer/dist/index.js as follows, I confirmed that server.node.js from Node.js is being imported.

const reactDom = await import("react-dom/server");
console.log("DEBUG: reactDom:", reactDom)
bun dev
$ vite

  VITE v5.3.3  ready in 94 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
(!) Could not auto-determine entry point from rollupOptions or html files and there are no explicit optimizeDeps.include patterns. Skipping dependency pre-bundling.
DEBUG: reactDom: [Module: null prototype] {
  default: {
    version: '19.0.0-rc-df783f9ea1-20240708',
    renderToString: [Function (anonymous)],
    renderToStaticMarkup: [Function (anonymous)],
    renderToPipeableStream: [Function (anonymous)]
  },
  renderToPipeableStream: [Function (anonymous)],
  renderToStaticMarkup: [Function (anonymous)],
  renderToString: [Function (anonymous)],
  resumeToPipeableStream: undefined,
  version: '19.0.0-rc-df783f9ea1-20240708'
}
TypeError: reactDom.renderToReadableStream is not a function
    at Context.<anonymous> (file:///Users/yoshikouki/src/github.com/tsuki-lab/hono-middleware-issue-627/node_modules/@hono/react-renderer/dist/index.js:10:35)
    at async dispatch (file:///Users/yoshikouki/src/github.com/tsuki-lab/hono-middleware-issue-627/node_modules/hono/dist/compose.js:29:17)
    at async dispatch (file:///Users/yoshikouki/src/github.com/tsuki-lab/hono-middleware-issue-627/node_modules/hono/dist/compose.js:29:17)
    at async file:///Users/yoshikouki/src/github.com/tsuki-lab/hono-middleware-issue-627/node_modules/hono/dist/hono-base.js:200:25
    at async getRequestListener.overrideGlobalObjects (file:///Users/yoshikouki/src/github.com/tsuki-lab/hono-middleware-issue-627/node_modules/@hono/vite-dev-server/dist/dev-server.js:69:32)
    at async responseViaResponseObject (file:///Users/yoshikouki/src/github.com/tsuki-lab/hono-middleware-issue-627/node_modules/@hono/node-server/dist/index.mjs:330:15)

https://github.com/facebook/react/blob/main/packages/react-dom/server.node.js

I will investigate potential workarounds when using @hono/vite-dev-server (such as running it as Edge environment) or if a fix for @hono/react-renderer is necessary.

@yusukebe if you have any ideas, please share.

yoshikouki commented 2 months ago

@tsuki-lab

To avoid this situation, you can use the --bun option when running vite

$ bun --bun x vite
Failed to find Response internal state key
(!) Could not auto-determine entry point from rollupOptions or html files and there are no explicit optimizeDeps.include patterns. Skipping dependency pre-bundling.

  VITE v5.3.3  ready in 179 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
DEBUG: reactDom: Module {
  default: {
    version: "19.0.0-rc-df783f9ea1-20240708",
    renderToReadableStream: [Function],
    renderToString: [Function],
    renderToStaticMarkup: [Function],
  },
  renderToReadableStream: [Function],
  renderToStaticMarkup: [Function],
  renderToString: [Function],
  version: "19.0.0-rc-df783f9ea1-20240708",
}

~As far as I remember, Bun has limited support for Vite to make it "work for now"~, but if you encounter any issues, please let me know.

(Vite was supported but not optimised)

While Vite currently works with Bun, it has not been heavily optimized, nor has Vite been adapted to use Bun's bundler, module resolver, or transpiler. https://bun.sh/guides/ecosystem/vite

tsuki-lab commented 2 months ago

@yoshikouki Thank you! I have confirmed that using bun run --bun vite works correctly in my environment.

Thank you for your support over the past few days.