diff --git a/packages/common/refresh-utils.ts b/packages/common/refresh-utils.ts index 559cbaa04..8c0cadc12 100644 --- a/packages/common/refresh-utils.ts +++ b/packages/common/refresh-utils.ts @@ -1,7 +1,7 @@ export const runtimePublicPath = '/@react-refresh' const reactCompRE = /extends\s+(?:React\.)?(?:Pure)?Component/ -const refreshContentRE = /\$Refresh(?:Reg|Sig)\$\(/ +const refreshContentRE = /\$RefreshReg\$\(/ // NOTE: this is exposed publicly via plugin-react export const preambleCode = `import { injectIntoGlobalHook } from "__BASE__${runtimePublicPath.slice( diff --git a/packages/plugin-react-oxc/CHANGELOG.md b/packages/plugin-react-oxc/CHANGELOG.md index 7648dec4d..2f93c2517 100644 --- a/packages/plugin-react-oxc/CHANGELOG.md +++ b/packages/plugin-react-oxc/CHANGELOG.md @@ -2,10 +2,14 @@ ## Unreleased -### Add `filter` for rolldown-vite +### Add `filter` for rolldown-vite [#470](https://github.com/vitejs/vite-plugin-react/pull/470) Added `filter` so that it is more performant when running this plugin with rolldown-powered version of Vite. +### Skip HMR for JSX files with hooks [#480](https://github.com/vitejs/vite-plugin-react/pull/480) + +This removes the HMR warning for hooks with JSX. + ## 0.1.1 (2025-04-10) ## 0.1.0 (2025-04-09) diff --git a/packages/plugin-react-swc/CHANGELOG.md b/packages/plugin-react-swc/CHANGELOG.md index 79ed6f409..aed49abc7 100644 --- a/packages/plugin-react-swc/CHANGELOG.md +++ b/packages/plugin-react-swc/CHANGELOG.md @@ -2,14 +2,18 @@ ## Unreleased -### Add `filter` for rolldown-vite +### Add `filter` for rolldown-vite [#470](https://github.com/vitejs/vite-plugin-react/pull/470) Added `filter` so that it is more performant when running this plugin with rolldown-powered version of Vite. -### Skip HMR preamble in Vitest browser mode +### Skip HMR preamble in Vitest browser mode [#478](https://github.com/vitejs/vite-plugin-react/pull/478) This was causing annoying `Sourcemap for "/@react-refresh" points to missing source files` and is unnecessary in test mode. +### Skip HMR for JSX files with hooks [#480](https://github.com/vitejs/vite-plugin-react/pull/480) + +This removes the HMR warning for hooks with JSX. + ## 3.9.0 (2025-04-15) ### Make compatible with rolldown-vite diff --git a/packages/plugin-react/CHANGELOG.md b/packages/plugin-react/CHANGELOG.md index ccb6b02c9..52105e6d6 100644 --- a/packages/plugin-react/CHANGELOG.md +++ b/packages/plugin-react/CHANGELOG.md @@ -2,10 +2,14 @@ ## Unreleased -### Add `filter` for rolldown-vite +### Add `filter` for rolldown-vite [#470](https://github.com/vitejs/vite-plugin-react/pull/470) Added `filter` so that it is more performant when running this plugin with rolldown-powered version of Vite. +### Skip HMR for JSX files with hooks [#480](https://github.com/vitejs/vite-plugin-react/pull/480) + +This removes the HMR warning for hooks with JSX. + ## 4.4.1 (2025-04-19) Fix type issue when using `moduleResolution: "node"` in tsconfig [#462](https://github.com/vitejs/vite-plugin-react/pull/462) diff --git a/playground/hook-with-jsx/__tests__/hook-with-jsx.spec.ts b/playground/hook-with-jsx/__tests__/hook-with-jsx.spec.ts new file mode 100644 index 000000000..570ca8174 --- /dev/null +++ b/playground/hook-with-jsx/__tests__/hook-with-jsx.spec.ts @@ -0,0 +1,27 @@ +import { expect, test } from 'vitest' +import { + editFile, + isServe, + page, + untilBrowserLogAfter, + untilUpdated, +} from '~utils' + +test('should render', async () => { + expect(await page.textContent('button')).toMatch('count is 0') + expect(await page.click('button')) + expect(await page.textContent('button')).toMatch('count is 1') +}) + +if (isServe) { + test('Hook with JSX HMR', async () => { + editFile('src/useButtonHook.tsx', (code) => + code.replace('count is {count}', 'count is {count}!'), + ) + await untilBrowserLogAfter( + () => page.textContent('button'), + '[vite] hot updated: /src/App.tsx', + ) + await untilUpdated(() => page.textContent('button'), 'count is 1!') + }) +} diff --git a/playground/hook-with-jsx/__tests__/oxc/hook-with-jsx.spec.ts b/playground/hook-with-jsx/__tests__/oxc/hook-with-jsx.spec.ts new file mode 100644 index 000000000..4696fae50 --- /dev/null +++ b/playground/hook-with-jsx/__tests__/oxc/hook-with-jsx.spec.ts @@ -0,0 +1 @@ +import '../hook-with-jsx.spec' diff --git a/playground/hook-with-jsx/index.html b/playground/hook-with-jsx/index.html new file mode 100644 index 000000000..96ad88a1c --- /dev/null +++ b/playground/hook-with-jsx/index.html @@ -0,0 +1,13 @@ + + + + + + + React hook with JSX + + +
+ + + diff --git a/playground/hook-with-jsx/package.json b/playground/hook-with-jsx/package.json new file mode 100644 index 000000000..6a7bbfd7a --- /dev/null +++ b/playground/hook-with-jsx/package.json @@ -0,0 +1,19 @@ +{ + "name": "@vitejs/test-hook-with-jsx", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@types/react": "^19.1.2", + "@types/react-dom": "^19.1.2", + "@vitejs/plugin-react": "workspace:*" + } +} diff --git a/playground/hook-with-jsx/public/vite.svg b/playground/hook-with-jsx/public/vite.svg new file mode 100644 index 000000000..4dcd77ad0 --- /dev/null +++ b/playground/hook-with-jsx/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/playground/hook-with-jsx/src/App.tsx b/playground/hook-with-jsx/src/App.tsx new file mode 100644 index 000000000..9e0ae242e --- /dev/null +++ b/playground/hook-with-jsx/src/App.tsx @@ -0,0 +1,6 @@ +import { useButtonHook } from './useButtonHook.tsx' + +export function App() { + const button = useButtonHook() + return
{button}
+} diff --git a/playground/hook-with-jsx/src/index.tsx b/playground/hook-with-jsx/src/index.tsx new file mode 100644 index 000000000..5e7046ce2 --- /dev/null +++ b/playground/hook-with-jsx/src/index.tsx @@ -0,0 +1,9 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import { App } from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/playground/hook-with-jsx/src/useButtonHook.tsx b/playground/hook-with-jsx/src/useButtonHook.tsx new file mode 100644 index 000000000..cae586690 --- /dev/null +++ b/playground/hook-with-jsx/src/useButtonHook.tsx @@ -0,0 +1,10 @@ +import { useState } from 'react' + +export function useButtonHook() { + const [count, setCount] = useState(0) + return ( + + ) +} diff --git a/playground/hook-with-jsx/tsconfig.json b/playground/hook-with-jsx/tsconfig.json new file mode 100644 index 000000000..c9e7d3d89 --- /dev/null +++ b/playground/hook-with-jsx/tsconfig.json @@ -0,0 +1,23 @@ +{ + "include": ["src"], + "compilerOptions": { + "module": "ESNext", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "target": "ESNext", + "jsx": "react-jsx", + "types": ["vite/client"], + "noEmit": true, + "isolatedModules": true, + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "useUnknownInCatchVariables": true + } +} diff --git a/playground/hook-with-jsx/vite.config.ts b/playground/hook-with-jsx/vite.config.ts new file mode 100644 index 000000000..6e5b8e40a --- /dev/null +++ b/playground/hook-with-jsx/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + server: { port: 8909 /* Should be unique */ }, + plugins: [react()], +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bb0724961..d0bcf61ef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -521,6 +521,25 @@ importers: specifier: ^5.8.3 version: 5.8.3 + playground/hook-with-jsx: + dependencies: + react: + specifier: ^19.1.0 + version: 19.1.0 + react-dom: + specifier: ^19.1.0 + version: 19.1.0(react@19.1.0) + devDependencies: + '@types/react': + specifier: ^19.1.2 + version: 19.1.2 + '@types/react-dom': + specifier: ^19.1.2 + version: 19.1.2(@types/react@19.1.2) + '@vitejs/plugin-react': + specifier: workspace:* + version: link:../../packages/plugin-react + playground/mdx: dependencies: react: