nitrojs / nitrojs/nitro

ReferenceError: $RefreshReg$ after upgrade to vite v8

Open
#4,154 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

tanstack v3
Dominant language
TypeScript
Stars
11.2k
Forks
899
Avg merge
2d 24m
Merged PRs (30d)
40

Description

Environment

Platform
"@tanstack/react-devtools": "^0.10.0",
"@tanstack/react-query": "^5.95.2",
"@tanstack/react-router": "^1.168.7",
"@tanstack/react-router-devtools": "^1.166.11",
"@tanstack/react-router-ssr-query": "^1.166.10",
"@tanstack/react-start": "^1.167.12",
"@tanstack/react-virtual": "^3.13.23",
"@tanstack/router-plugin": "^1.167.8",

OS: Ubuntu 24 on WSL2 (windows)
Browser: Chrome, Ms Edge
Bun v1.3.11

Reproduction

Previously I use vite 7 on my tanstack project, this work prefectly, but after I upgrade to vite v8, any route link cannot be clicked, and on browser I got Uncaught (in promise) ReferenceError: $RefreshReg$ is not defined

My stack is tanstack start, nitro, bun

Your Example Website or App

https://localhost:3000

Steps to Reproduce the Bug or Issue

here my package.json

{
  "name": "start-app",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "bunx --bun vite dev",
    "build": "bunx --bun vite build",
    "preview": "bunx --bun vite preview",
    "test": "bunx --bun vitest run",
    "lint": "eslint",
    "format": "prettier",
    "check-types": "tsc --noEmit",
    "check": "prettier --write . && eslint --fix && tsc --noEmit",
    "playwright": "bunx playwright",
    "ui": "bunx --bun shadcn@latest",
    "db:generate": "drizzle-kit generate",
    "db:introspect": "drizzle-kit introspect",
    "db:introspect-current": "drizzle-kit pull",
    "db:pull-tables": "drizzle-kit pull --config=drizzle-pull.config.ts"
  },
  "dependencies": {
    "@ai-sdk/google": "^3.0.53",
    "@ai-sdk/react": "^3.0.142",
    "@aws-sdk/cloudfront-signer": "^3.1012.0",
    "@base-ui/react": "^1.3.0",
    "@fontsource-variable/inter": "^5.2.8",
    "@radix-ui/react-use-controllable-state": "^1.2.2",
    "@rive-app/react-webgl2": "^4.27.3",
    "@streamdown/math": "^1.0.2",
    "@tailwindcss/vite": "^4.2.2",
    "@tanstack/react-devtools": "^0.10.0",
    "@tanstack/react-query": "^5.95.2",
    "@tanstack/react-router": "^1.168.7",
    "@tanstack/react-router-devtools": "^1.166.11",
    "@tanstack/react-router-ssr-query": "^1.166.10",
    "@tanstack/react-start": "^1.167.12",
    "@tanstack/react-virtual": "^3.13.23",
    "@tanstack/router-plugin": "^1.167.8",
    "ai": "^6.0.140",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "cmdk": "^1.1.1",
    "date-fns": "^4.1.0",
    "drizzle-orm": "beta",
    "input-otp": "^1.4.2",
    "jose": "^6.2.2",
    "lucide-react": "latest",
    "motion": "^12.38.0",
    "nanoid": "^5.1.7",
    "nitro": "latest",
    "react": "^19.2.4",
    "react-day-picker": "^9.14.0",
    "react-dom": "^19.2.4",
    "shadcn": "^4.1.0",
    "sonner": "^2.0.7",
    "streamdown": "^2.5.0",
    "tailwind-merge": "^3.5.0",
    "tailwindcss": "^4.2.2",
    "tw-animate-css": "^1.4.0",
    "use-stick-to-bottom": "^1.1.3",
    "vaul": "^1.1.2",
    "zod": "^4.3.6"
  },
  "devDependencies": {
    "@faker-js/faker": "^10.4.0",
    "@playwright/test": "^1.58.2",
    "@tanstack/cli": "^0.62.4",
    "@tanstack/devtools-vite": "^0.6.0",
    "@tanstack/eslint-config": "^0.4.0",
    "@tanstack/react-query-devtools": "^5.95.2",
    "@types/bun": "^1.3.11",
    "@types/react": "^19.2.14",
    "@vitejs/plugin-react": "^6.0.1",
    "drizzle-kit": "beta",
    "jsdom": "^29.0.1",
    "prettier": "^3.8.1",
    "prettier-plugin-tailwindcss": "^0.7.2",
    "typescript": "^6.0.2",
    "vite": "^8.0.3",
    "vitest": "^4.1.2",
    "web-vitals": "^5.2.0"
  }
}

here my tsconfig.json

{
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "eslint.config.js",
    "prettier.config.js",
    "vite.config.js"
  ],
  "exclude": ["node_modules", "drizzle/pulled"],
  "compilerOptions": {
    "target": "ES2022",
    "jsx": "react-jsx",
    "module": "ESNext",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "types": ["bun", "vite/client"],

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "verbatimModuleSyntax": false,
    "noEmit": true,

    /* Linting */
    "skipLibCheck": true,
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true,
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

here my vite.config.ts

import { defineConfig } from 'vite'
import { devtools } from '@tanstack/devtools-vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import viteReact from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import { nitro } from 'nitro/vite'

const config = defineConfig({
  resolve: {
    tsconfigPaths: true,
  },
  plugins: [
    devtools(),
    tanstackStart(),
    nitro({
      preset: 'bun',
    }),
    viteReact(),
    tailwindcss(),
  ],
  optimizeDeps: {
    exclude: ['bun'],
  },
})

export default config

here my src/routes/__root.tsx

import {
  HeadContent,
  Scripts,
  createRootRouteWithContext,
} from '@tanstack/react-router'
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
import { TanStackDevtools } from '@tanstack/react-devtools'
import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'
import appCss from '../styles.css?url'
import type { AppSession } from '@/lib/server/session'
import { Toaster } from '@/components/ui/sonner'
import { DefaultNotFound } from '@/components/default-not-found'
import { DefaultCatchBoundary } from '@/components/default-catch-boundary'
import { getAppSessionFn } from '@/lib/server/session'
import { DirectionProvider } from '@/components/ui/direction'

interface RouterContext {
  session: AppSession | null
}

export const Route = createRootRouteWithContext<RouterContext>()({
  beforeLoad: async () => {
    const session = await getAppSessionFn()
    return { session }
  },

  head: () => ({
    meta: [
      {
        charSet: 'utf-8',
      },
      {
        name: 'viewport',
        content: 'width=device-width, initial-scale=1',
      },
    ],
    links: [
      {
        rel: 'stylesheet',
        href: appCss,
      },
    ],
  }),

  shellComponent: RootDocument,
  notFoundComponent: DefaultNotFound,
  errorComponent: DefaultCatchBoundary,
})

function RootDocument({ children }: { children: React.ReactNode }) {
  const isDevelopment = process.env.DEV
  return (
    <html lang="en" dir="ltr" suppressHydrationWarning>
      <head>
        <HeadContent />
      </head>
      <body>
        <DirectionProvider direction="ltr">
          {children}
          <Toaster richColors />
        </DirectionProvider>
        {isDevelopment && (
          <TanStackDevtools
            config={{
              position: 'bottom-right',
            }}
            plugins={[
              {
                name: 'TanStack Query',
                render: <ReactQueryDevtoolsPanel />,
              },
              {
                name: 'Tanstack Router',
                render: <TanStackRouterDevtoolsPanel />,
              },
            ]}
          />
        )}
        <Scripts />
      </body>
    </html>
  )
}

here my src/router.tsx

import { createRouter } from '@tanstack/react-router'
import { MutationCache, QueryClient } from '@tanstack/react-query'
import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query'

// Import the generated route tree
import { routeTree } from './routeTree.gen'

// Create a new query client
export const queryClient = new QueryClient({
  mutationCache: new MutationCache({
    onSuccess: () => {
      queryClient.invalidateQueries()
    },
  }),
  defaultOptions: {
    queries: {
      staleTime: 10_000,
    },
  },
})

// Create a new router instance
export const getRouter = () => {
  const router = createRouter({
    routeTree,
    scrollRestoration: true,
    defaultPreloadStaleTime: 0,
    defaultPreload: 'intent',
    defaultPreloadDelay: 100,
    context: {
      session: null,
    },
  })

  setupRouterSsrQueryIntegration({
    router,
    queryClient,
  })

  return router
}

Describe the bug

I expect all link can work, and browser not show sonner.tsx:43 Uncaught (in promise) ReferenceError: $RefreshReg$ is not defined
at sonner.tsx:43:10

this is not only sonner, I try to remove sonner, the error move to button.tsx, and so on

Additional context

I dont know this issue because other dependency, on tanstack start side, or nitro side, or other
But I also add issue https://github.com/TanStack/router/issues/7059

Logs

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with vite.config.ts, src/routes/__root.tsx, and src/router.tsx, then run the reported Bun/Vite 8 development setup to reproduce the $RefreshReg$ error when following a route link. Trace which entry point loads the failing sonner.tsx or button.tsx module; done means route links work without the browser ReferenceError.

Written by the indexing model from the issue text.

Assessment

Tech stack
bun, react, typescript, vite
Domain
build-system, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.