vite-plugins icon indicating copy to clipboard operation
vite-plugins copied to clipboard

Add support to React Refresh

Open gaetan-puleo opened this issue 1 year ago • 13 comments

React refresh is not working when using @hono/vite-dev-server and vite-react-plugin.

To make it works, we should transform the HTML with viteServer.transformIndexHtml(req.url, html)

https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react

gaetan-puleo avatar Jun 07 '24 12:06 gaetan-puleo

It could be possible to do it here https://github.com/honojs/vite-plugins/blob/main/packages/dev-server/src/dev-server.ts#L168

The issue is we are using Stream here.

gaetan-puleo avatar Jun 07 '24 12:06 gaetan-puleo

As a workaround take a look here. https://github.com/honojs/vite-plugins/pull/142#issuecomment-2155096162

gaetan-puleo avatar Jun 07 '24 15:06 gaetan-puleo

We can close the issue if you want @yusukebe or we can wait for an "official way" to do it.

gaetan-puleo avatar Jun 07 '24 15:06 gaetan-puleo

hey @yusukebe! i came across this issue while trying to implement your hono-vite-react plugin for bun. i really like the ssr approach (instead of statically serving index.html).

when running the dev server though, i'd get the following error in the browser:

@vitejs/plugin-react can't detect preamble

ultimately, it looks like i solved the issue with vite's recommended approach for backend integration: adding this script to the top of my index.html

import RefreshRuntime from 'http://localhost:5173/@react-refresh'
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true

how is it that your implementation doesn't require this? it looks like @cloudflare/vite-plugin does call viteServer.transformIndexHtml, but it's not clear to me whether that's relevant.

i'm mostly curious about how to best use hono + react + vite, but also wondering whether i've missed something in my implementation

ambergristle avatar Apr 06 '25 19:04 ambergristle

Hi @ambergristle !

The hono-vite-react-stack uses the vite-plugin-ssr-hot-reload which I made will inject the script for "react-refresh":

https://github.com/yusukebe/vite-plugin-ssr-hot-reload/blob/main/src/plugin.ts#L77-L86

So that is the answer.

I've created the hono-vite-react-stack for the practical use cases that include libs in the mainstream: React and Tailwind CSS. So, I think it's best to use that plugin for the same purpose instead of that you create your own plugin. Or the plugin you want to make has other features?

yusukebe avatar Apr 07 '25 08:04 yusukebe

thanks for the quick reply @yusukebe!

i had installed vite-plugin-ssr-hot-reload but still got the error. thanks for confirming that it should inject the script. i'll try and reproduce the issue and see if i can figure out what's going on.

it looks like hono-vite-react-stack is for projects running on cloudflare. is that right? i like to build on bun, so i'm adapting your implementation to use bun plugins. i don't plan on publishing it or anything; just learning how vite works.

edit: I think I've narrowed down the issue to this line: https://github.com/yusukebe/vite-plugin-ssr-hot-reload/blob/530e0bfbc4fdaea3cf440dbf2766a339f0b31bc3/src/plugin.ts#L65

content-type is logging undefined at that line (no headers are included in res), so res.end early-returns. i'm using reactRenderer with c.render, and the content-type does get set by the time the request is resolved, so i'm not sure what's going on.

for reference, this also shows content-type set:

app.use('*', async (c, next) => {
  await next()
  console.log(c.res) // "content-type": "text/html; charset=UTF-8"
})

edit: it looks like the issue is that the request for the index (that returns html) isn't going through the middleware added by ssrHotReload

edit: probably not relevant, but this line in @hono/node-server (via @hono/vite-dev-server) is executed on server start: https://github.com/honojs/node-server/blob/99ad1703fd3aa60853fbdfab880271ac88343016/src/response.ts#L88

if (!stateKey) {
  console.warn('Failed to find Response internal state key')
}

ambergristle avatar Apr 07 '25 12:04 ambergristle

@ambergristle

it looks like hono-vite-react-stack is for projects running on cloudflare. is that right? i like to build on bun, so i'm adapting your implementation to use bun plugins. i don't plan on publishing it or anything; just learning how vite works.

Yes. It is just for Cloudflare. But it's great making it for Bun!

Basically, it will be successful just using vite-plugin-ssr-hot-reload that I make for the purpose.

Can you share the project that you are working on?

yusukebe avatar Apr 08 '25 07:04 yusukebe

@yusukebe here's my repo: https://github.com/ambergristle/hono-react

i'll keep trying to track down the issue, but i'm still trying to wrap my head around vite, so i appreciate any feedback you might have!

ambergristle avatar Apr 08 '25 21:04 ambergristle

@yusukebe i managed to resolve the issue by changing the plugin order, specifically by calling ssrHotReload before devServer. here's the commit. only the vite.config.ts update is relevant: https://github.com/ambergristle/hono-react/commit/06aa534ac9dc5fe206801b66157bb4d8b9574931

let me know if you have any insight into why this works though

ambergristle avatar Apr 09 '25 13:04 ambergristle

Hey @ambergristle

Thank you for providing the repo. I've investigated. As you said, you should put the ssrHotReload before devServer. The ssrHotReload will be applied when the content-type is text/html, but the content-type is not fixed if devServer is executed first.

And I fixed the minor bug of vite-plugin-ssr-hot-reload and released it as 0.4.2. So it should be a success if you update it and set up the order of them correctly.

yusukebe avatar Apr 11 '25 09:04 yusukebe

thanks @yusukebe! it works great

could you share a little more about why content-type isn't fixed if devServer is executed first? is it because devServer formats and returns the response?

ambergristle avatar Apr 11 '25 10:04 ambergristle

@ambergristle That's great!

could you share a little more about why content-type isn't fixed if devServer is executed first? is it because devServer formats and returns the response?

Honestly, I could not find the reason yet. If you use only devServer, the content type will be set as text/html correctly. So, it's an issue only the case when combinating some plugins. I think it will take time, so I give up it now 🙃

yusukebe avatar Apr 12 '25 00:04 yusukebe

@yusukebe fair enough. I'll look into it if I have some time

ambergristle avatar Apr 12 '25 07:04 ambergristle