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

[TanStack Start] HMR is not working from root route (__root) #1992

Open
iamchanii opened this issue Jul 19, 2024 · 35 comments
Open

[TanStack Start] HMR is not working from root route (__root) #1992

iamchanii opened this issue Jul 19, 2024 · 35 comments
Labels
start Everything about TanStack Start

Comments

@iamchanii
Copy link
Contributor

Describe the bug

HMR is not working in root route. only working from normal routes.

Your Example Website or App

https://github.com/TanStack/router/tree/main/examples/react/start-basic-rsc

Steps to Reproduce the Bug or Issue

  1. Clone (or copy or degit) start-basic-rsc example, install dependencies and run dev server.
  2. Open http://localhost:3000
  3. Try to edit from __root.tsx. I just added a link beside Home.

Expected behavior

In terminal, dev server printed a log about page has reloaded.

[vite] page reload app/routes/__root.tsx

but the changes are not reflected in the browser.

Screenshots or Videos

2024-07-19.19.22.35.mov

Platform

  • OS: macOs
  • Browser: Arc / Chrome
  • Version: 126.0.6478.127

Additional context

No response

@schiller-manuel schiller-manuel added the start Everything about TanStack Start label Jul 19, 2024
@anulman
Copy link

anulman commented Aug 2, 2024

I'm experiencing this as well, not just in my root route but in any top-level route.

I also have not been able to separate out components/Foo.tsx files and have them hot-reload. The dev console & JS console confirm the HMR event has been emitted and received, but the React JS—even for route sub-components modified in non-route files (e.g. import { FooPage } from '~/components/FooPage';) does not re-render the HMR'ed component.

@ChrisEdgington
Copy link

ChrisEdgington commented Aug 9, 2024

We just added TanStack router to our vite-based project, and now we are also experiencing this HMR failure. I tried a few different routes, it does seem to only be happening with __root.tsx.

@KiwiKilian
Copy link

KiwiKilian commented Aug 12, 2024

To summarize, we see the following HMR problems with file based routing:

HMR is not triggered when editing

  • routes/__root.tsx
  • components/Example.tsx imported into any routes/**.tsx file
  • routes/_layout.tsx

HMR is triggered when editing

  • routes/index.tsx
  • routes/example.example.tsx (@anulman are you sure this doesn't work for any plain route (no _ prefix) file?)
  • routes/with-directory/example.tsx

Reproduction

All of this can be testet with the Start Basic StackBlitz. Create a new File app/components/Example.tsx:

export function Example() {
  return <h1>Changing this will not trigger HMR</h1>
}

Now import this into app/routes/index.tsx and render <Example />:

import { createFileRoute } from '@tanstack/react-router'
import { Example } from '~/components/Example'

export const Route = createFileRoute('/')({
  component: Home,
})

function Home() {
  return (
    <div className="p-2">
      <h3>Welcome Home!!!</h3>
      <Example />
    </div>
  )
}

While editing "Welcome Home!!!" will trigger HMR, editing "Changing this will not trigger HMR" will not. The latter shows

[vite] hmr update /app/components/Example.tsx

in the console, but a manual reload is necessary.

@rin-yato
Copy link

rin-yato commented Sep 6, 2024

Having the same problem for routes/page-a/-component/example.tsx

@jwtong
Copy link

jwtong commented Sep 6, 2024

Bump, this happens on routes at random

@schiller-manuel
Copy link
Contributor

schiller-manuel commented Sep 7, 2024

can you please test out the package built for this PR whether it fixes the HMR issues you are experiencing: #2286 (comment)

@jwtong
Copy link

jwtong commented Sep 10, 2024

can you please test out the package built for this PR whether it fixes the HMR issues you are experiencing: #2286 (comment)

"@tanstack/router": "github:lithdew/router#main"

Installed as above, still had the same issue though. Updates to pages don't hot reload.

@jwtong
Copy link

jwtong commented Sep 10, 2024

Hmm, yeah looks like I'm not sure how to install your forked version to @tanstack/react-router.

@KiwiKilian
Copy link

KiwiKilian commented Sep 17, 2024

@schiller-manuel I've tried both #2286 and #2316. Both seem to fix the problem in their current state.

@jwtong make sure to unfold the instructions in the comments on how to install from a pr. You can either use install/add with your prefered package manager or change the version in your package.json to the URL provided. E.g. testing the #2316 looks like this in our package.json:

    "@tanstack/react-router": "https://pkg.pr.new/@tanstack/react-router@2316",
    "@tanstack/react-router-with-query": "https://pkg.pr.new/@tanstack/react-router-with-query@2316",
    "@tanstack/start": "https://pkg.pr.new/@tanstack/start@2316",

Make sure all @tanstack packages use the same "version" (rather now PR URL).

@jwtong
Copy link

jwtong commented Sep 17, 2024

@KiwiKilian @schiller-manuel

Tested both #2286 and #2316.

For me, it did not resolve the issue. If I edit a route file (e.g. apps/web/src/routes/_auth._nav.member.clients.index.tsx), I'm still not seeing updates until I refresh the page.

I tested by just adding content inside a <div>Hello</div>

@KiwiKilian
Copy link

It works for me on #2316 (version 1.58.5 and hash 684eef6) when editing app/routes/_authenticated.index.tsx like just adding some text or changing.

@pedrobzz
Copy link

none of those fixed my issue. I'm not using tanstack start, only tanstack router, but i have the exact same problem

@MarkSFrancis
Copy link

MarkSFrancis commented Oct 7, 2024

For anyone reading this who's looking for a workaround until a fix is merged, you can add the following to your __root.tsx to enable HMR in Tanstack Start:

export const Route = createRootRoute({
  // Other route props like the component
  // ...
  //
  scripts: () =>
    import.meta.env.DEV
      ? [
          {
            type: 'module',
            children: `import RefreshRuntime from "/_build/@react-refresh";
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type`,
          },
        ]
      : [],
});

This does the same thing as #2286 and #2316 (albeit in a slightly more hacky way). Once the fix is merged, you should be able to safely remove this code from your __root.tsx again

@cameronb23
Copy link

@MarkSFrancis Lifesaver, been trying to work Start into a side project of mine and was pretty sad about the HMR (but its alpha so who cares). A great fix for now until the team gets it going!

@aaronksaunders
Copy link

@MarkSFrancis - worked wonders for me trying to get authentication working, as soon as i added useServerFn everything exploded!! Found this issue and things are rolling again

@dmagunov
Copy link

dmagunov commented Nov 3, 2024

Hi, I'm experiencing the same issue with TanStack/Router. HMR doesn't working when I make changes in __root.tsx. I've tried various combinations of TanStack/Router (version 1.78.3 and below) with Vite (version 5.4.10 and below) using React/React SWC, but nothing has worked. I also tried @MarkSFrancis's workaround without success.

@dmagunov
Copy link

dmagunov commented Nov 3, 2024

Extracting root route component fixed an issue (thanks Claude):

From:

createRootRoute({
  component: () => (<></>)
});

To:

createRootRoute({
  component: RootComponent
});

@dh94
Copy link

dh94 commented Nov 3, 2024

Extracting root route component fixed an issue (thanks Claude):

From:

createRootRoute({
component: () => (<></>)
});
To:

createRootRoute({
component: RootComponent
});

For me this was the issue in all routes! bless you

@notKamui
Copy link

notKamui commented Nov 6, 2024

Currently, while the page is indeed reloaded upon file modification, it does a full page reload instead of a HMR. But this only happens on regular routes, not the __root route (on which HMR works). Using Tanstack Start

@vKongv
Copy link

vKongv commented Nov 17, 2024

Currently, while the page is indeed reloaded upon file modification, it does a full page reload instead of a HMR. But this only happens on regular routes, not the __root route (on which HMR works). Using Tanstack Start

I am experiencing full reload too. Not sure what am i missing. Using Start

@yassine-safraoui
Copy link

For anyone reading this who's looking for a workaround until a fix is merged, you can add the following to your __root.tsx to enable HMR in Tanstack Start:

export const Route = createRootRoute({
// Other route props like the component
// ...
//
scripts: () =>
import.meta.env.DEV
? [
{
type: 'module',
children: import RefreshRuntime from "/_build/@react-refresh"; RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type,
},
]
: [],
});
This does the same thing as #2286 and #2316 (albeit in a slightly more hacky way). Once the fix is merged, you should be able to safely remove this code from your __root.tsx again

I get type errors when i try to add the script like you did, I tried doing the same thing by replacing scripts with loader or beforeReload but to no avail. i'm using tanstack router( not start) with vite, when I edit and save a component in a file that starts with "-"( inside my routes folder to ignore it) I don't see any changes, not even a full page reload let alone HMR. This is super annoying I guess I can't continue with tanstack router for the time being unfortunately :((

@shestaya-liniya
Copy link

@yassine-safraoui same :(

@sngmn451
Copy link

sngmn451 commented Nov 28, 2024

app/routes/__root.tsx

<head>
...
  {import.meta.env.DEV && (
    <script
      type="module"
      dangerouslySetInnerHTML={{
        __html: `import RefreshRuntime from "/_build/@react-refresh";
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type`
      }}
    />
  )}
</head>

This work for me

@shestaya-liniya
Copy link

@sngmn451 thank you! worked for me too

@yassine-safraoui
Copy link

yassine-safraoui commented Nov 28, 2024

app/routes/__root.tsx

... {import.meta.env.DEV && ( <script type="module" dangerouslySetInnerHTML={{ __html: `import RefreshRuntime from "/_build/@react-refresh"; RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type` }} /> )} This work for me

not for me :((
doing it like this:
function RootComponent() { return ( <> <head> <script type="module" dangerouslySetInnerHTML={{ __html: ``import RefreshRuntime from "/_build/@react-refresh"; RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type``, }} /> </head> <Outlet />; </> ); }
gives this error: cannot appear as a child of

. it does because at the end all of the stuff in __root goes in the root div in index.html, if I remove the head and keep just the script, it does not work, if I try to add the script manually to the head in the index.html I get errors because I can't import there, even when specifying script type to module.

@timbo-tj
Copy link

timbo-tj commented Dec 4, 2024

@MarkSFrancis Thanks!

It didn't work for me at first. I had to marked my Route components for export and now it works!

ie instead of:

export const Route = createFileRoute('/')({
     component: RouteComponent,
   ...
})

function RouteComponent() {
   ...
}

I had to do:

export const Route = createFileRoute('/')({
     component: RouteComponent,
   ...
})

export function RouteComponent() {
   ...
}

@notKamui
Copy link

notKamui commented Dec 4, 2024

@timbo-tj I don't think this is what you actually want. I works for the wrong reason: Vite cannot do HMR when you export components and non components in the same file. When you do so, it will fallback to full page reloads, which is why you think reload works. I mean, it does, but it's not HMR.

@timbo-tj
Copy link

timbo-tj commented Dec 4, 2024

@notKamui Hmmm, I won't claim to understand what Vite + HMR is doing or why...! but this is my experience:

Recording.2024-12-04.190333.1.webm

It doesn't seem like a full page reload. (I need to search for my app again on each page load).

@PhilipGrefe
Copy link

FYI I'm experiencing the same issue (all expect the root routes perform a full reload) when enabling autoCodeSplitting in my tsr.config.json 🫤

{
  "autoCodeSplitting": true
}

@mcintyret
Copy link

Any updates on when #2316 will merge?

Will this also fix HMR when using SWC?

@SoloReverse
Copy link

My problem was there was no HMR in components only but it was working in routes. I used @MarkSFrancis 's Fix but had to remove the import. this is what worked for me was, I added the following to the head without the import.meta.env.dev. figured I'll just comment it out from builds but it works.

    scripts: [
      {
        type: "module",
        children: `import RefreshRuntime from "/_build/@react-refresh";
    RefreshRuntime.injectIntoGlobalHook(window)
    window.$RefreshReg$ = () => {}
    window.$RefreshSig$ = () => (type) => type`,
      },
    ],

FYI I'm using TanStack Start

@baptisteArno
Copy link

This is crazy HMR is not working on any file outside of the routes folder (Tanstack Start) ? Since September ?

@jonathanbecerra
Copy link

I was pulling my hair and wondering why my changes outside of the routes/ but still under app/ are not properly watched.
I find it odd that vite's hrm alludes that it did update when it didn't. Main reason for the hair pulling. Example of my console:

4:54:13 PM [vite] (client) hmr update /app/components/SideBarMenu.tsx, /app/styles/app.css?direct

My working directory as followed:

app
├── api.tsx
├── client.tsx
├── components
│   ├── SideBarMenu.tsx // -> This does not update ❌
├── routes // -> Anything under routes does update ✅
│   ├── __root.tsx 

My `package.json' has the following:

    "@tanstack/react-query": "^5.62.10",
    "@tanstack/react-query-devtools": "^5.62.10",
    "@tanstack/react-router": "^1.92.3",
    "@tanstack/react-router-with-query": "^1.92.3",
    "@tanstack/router-devtools": "^1.92.3",
    "@tanstack/router-plugin": "^1.91.1",
    "@tanstack/start": "^1.92.4",

The workaround on this thread that adds a script tag injecting the refresh runtime will throw an error if added to the __root.tsx or anywhere else. The error thrown in the browser is the following:

[plugin:vite-plugin-tanstack-start-create-server-fn] We detected that the '@vitejs/plugin-react' was passed before '@tanstack/start-vite-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: 
e.g.

plugins: [
  TanStackStartVite(), // Place this before viteReact()
  viteReact(),
]
app/routes/__root.tsx
    at TransformPluginContext.transform (file://node_modules/.pnpm/@tanstack+start-vite-plugin@1.91.1/node_modules/@tanstack/start-vite-plugin/dist/esm/index.js:33:15)
    at EnvironmentPluginContainer.transform (file://node_modules/.pnpm/vite@6.0.6_@types+node@22.10.2_jiti@2.4.2_terser@5.37.0_tsx@4.19.2_yaml@2.6.1/node_modules/vite/dist/node/chunks/dep-0AosnpPU.js:47220:19)
    at async loadAndTransform (file://node_modules/.pnpm/vite@6.0.6_@types+node@22.10.2_jiti@2.4.2_terser@5.37.0_tsx@4.19.2_yaml@2.6.1/node_modules/vite/dist/node/chunks/dep-0AosnpPU.js:41030:27)
    at async viteTransformMiddleware (file://node_modules/.pnpm/vite@6.0.6_@types+node@22.10.2_jiti@2.4.2_terser@5.37.0_tsx@4.19.2_yaml@2.6.1/node_modules/vite/dist/node/chunks/dep-0AosnpPU.js:42474:24
Click outside, press Esc key, or fix the code to dismiss.
You can also disable this overlay by setting server.hmr.overlay to false in vite.config.js.

Any new suggestions will be happy to add to test. For now we keep manually ⌘ + r. Happy holidays

@menisck
Copy link

menisck commented Jan 1, 2025

I was pulling my hair and wondering why my changes outside of the routes/ but still under app/ are not properly watched. I find it odd that vite's hrm alludes that it did update when it didn't. Main reason for the hair pulling. Example of my console:

4:54:13 PM [vite] (client) hmr update /app/components/SideBarMenu.tsx, /app/styles/app.css?direct
My working directory as followed:

app
├── api.tsx
├── client.tsx
├── components
│ ├── SideBarMenu.tsx // -> This does not update ❌
├── routes // -> Anything under routes does update ✅
│ ├── __root.tsx
My `package.json' has the following:

"@tanstack/react-query": "^5.62.10",
"@tanstack/react-query-devtools": "^5.62.10",
"@tanstack/react-router": "^1.92.3",
"@tanstack/react-router-with-query": "^1.92.3",
"@tanstack/router-devtools": "^1.92.3",
"@tanstack/router-plugin": "^1.91.1",
"@tanstack/start": "^1.92.4",

The workaround on this thread that adds a script tag injecting the refresh runtime will throw an error if added to the __root.tsx or anywhere else. The error thrown in the browser is the following:

[plugin:vite-plugin-tanstack-start-create-server-fn] We detected that the '@vitejs/plugin-react' was passed before '@tanstack/start-vite-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again:
e.g.

plugins: [
TanStackStartVite(), // Place this before viteReact()
viteReact(),
]
app/routes/root.tsx
at TransformPluginContext.transform (file://node_modules/.pnpm/@TanStack[email protected]/node_modules/@tanstack/start-vite-plugin/dist/esm/index.js:33:15)
at EnvironmentPluginContainer.transform (file://node_modules/.pnpm/[email protected]
@types[email protected][email protected][email protected][email protected][email protected]/node_modules/vite/dist/node/chunks/dep-0AosnpPU.js:47220:19)
at async loadAndTransform (file://node_modules/.pnpm/[email protected]
@types[email protected][email protected][email protected][email protected][email protected]/node_modules/vite/dist/node/chunks/dep-0AosnpPU.js:41030:27)
at async viteTransformMiddleware (file://node_modules/.pnpm/vite@6.0.6_@types[email protected][email protected][email protected][email protected][email protected]/node_modules/vite/dist/node/chunks/dep-0AosnpPU.js:42474:24
Click outside, press Esc key, or fix the code to dismiss.
You can also disable this overlay by setting server.hmr.overlay to false in vite.config.js.
Any new suggestions will be happy to add to test. For now we keep manually ⌘ + r. Happy holidays

I'm facing the same issue...

@lFitzl
Copy link

lFitzl commented Jan 5, 2025

I had to do this to get it to work....

Image

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

No branches or pull requests