diff --git a/packages/plugin-react-swc/playground/bundled-dev/__tests__/bundled-dev.spec.ts b/packages/plugin-react-swc/playground/bundled-dev/__tests__/bundled-dev.spec.ts
new file mode 100644
index 000000000..6fb03381c
--- /dev/null
+++ b/packages/plugin-react-swc/playground/bundled-dev/__tests__/bundled-dev.spec.ts
@@ -0,0 +1,16 @@
+import { expect, test } from '@playwright/test'
+import { setupDevServer } from '../../utils.ts'
+
+test('bundledDev mode does not throw config.server error', async ({ page }) => {
+ // The key verification: the dev server should start successfully
+ // without the "Cannot read properties of undefined (reading 'config')" error
+ // that the bug report (#1271) describes.
+ const { testUrl, server } = await setupDevServer('bundled-dev')
+
+ // Verify the server responds to requests (no crash)
+ await page.goto(testUrl)
+ const bodyText = await page.textContent('body')
+ expect(bodyText).toBeTruthy()
+
+ await server.close()
+})
diff --git a/packages/plugin-react-swc/playground/bundled-dev/index.html b/packages/plugin-react-swc/playground/bundled-dev/index.html
new file mode 100644
index 000000000..fb1aeef55
--- /dev/null
+++ b/packages/plugin-react-swc/playground/bundled-dev/index.html
@@ -0,0 +1,2 @@
+
+
diff --git a/packages/plugin-react-swc/playground/bundled-dev/package.json b/packages/plugin-react-swc/playground/bundled-dev/package.json
new file mode 100644
index 000000000..da71b9337
--- /dev/null
+++ b/packages/plugin-react-swc/playground/bundled-dev/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "playground-bundled-dev",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "debug": "node --inspect-brk vite",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "react": "^19.2.7",
+ "react-dom": "^19.2.7"
+ },
+ "devDependencies": {
+ "@types/react": "^19.2.17",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react-swc": "../../dist"
+ }
+}
diff --git a/packages/plugin-react-swc/playground/bundled-dev/src/App.tsx b/packages/plugin-react-swc/playground/bundled-dev/src/App.tsx
new file mode 100644
index 000000000..7d9c3a262
--- /dev/null
+++ b/packages/plugin-react-swc/playground/bundled-dev/src/App.tsx
@@ -0,0 +1,14 @@
+import { useState } from 'react'
+
+export default function App() {
+ const [count, setCount] = useState(0)
+
+ return (
+ <>
+ Hello Vite + React
+
+ >
+ )
+}
diff --git a/packages/plugin-react-swc/playground/bundled-dev/src/main.tsx b/packages/plugin-react-swc/playground/bundled-dev/src/main.tsx
new file mode 100644
index 000000000..1f5976c1d
--- /dev/null
+++ b/packages/plugin-react-swc/playground/bundled-dev/src/main.tsx
@@ -0,0 +1,4 @@
+import ReactDOM from 'react-dom/client'
+import App from './App.tsx'
+
+ReactDOM.createRoot(document.getElementById('app')!).render()
diff --git a/packages/plugin-react-swc/playground/bundled-dev/tsconfig.json b/packages/plugin-react-swc/playground/bundled-dev/tsconfig.json
new file mode 100644
index 000000000..195fe84e7
--- /dev/null
+++ b/packages/plugin-react-swc/playground/bundled-dev/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "include": ["src"],
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM"],
+ "types": ["vite/client"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ }
+}
diff --git a/packages/plugin-react-swc/playground/bundled-dev/vite.config.ts b/packages/plugin-react-swc/playground/bundled-dev/vite.config.ts
new file mode 100644
index 000000000..6c4b5d2b4
--- /dev/null
+++ b/packages/plugin-react-swc/playground/bundled-dev/vite.config.ts
@@ -0,0 +1,11 @@
+import react from '@vitejs/plugin-react-swc'
+import { defineConfig } from 'vite'
+
+export default defineConfig({
+ base: '/bundled-dev/',
+ server: { port: 8910 /* Should be unique */ },
+ experimental: {
+ bundledDev: true,
+ },
+ plugins: [react()],
+})
diff --git a/packages/plugin-react-swc/src/index.ts b/packages/plugin-react-swc/src/index.ts
index 50aee52bc..de0513940 100644
--- a/packages/plugin-react-swc/src/index.ts
+++ b/packages/plugin-react-swc/src/index.ts
@@ -78,6 +78,7 @@ const usingRolldown = 'rolldownVersion' in vite
const react = (_options?: Options): Plugin[] => {
let hmrDisabled = true
+ let isBundledDev = false
let viteCacheRoot: string | undefined
const options = {
jsxImportSource: _options?.jsxImportSource ?? 'react',
@@ -143,6 +144,9 @@ const react = (_options?: Options): Plugin[] => {
},
configResolved(config) {
viteCacheRoot = config.cacheDir
+ if (config.experimental.bundledDev) {
+ isBundledDev = true
+ }
hmrDisabled = config.server.hmr === false
const mdxIndex = config.plugins.findIndex(
(p) => p.name === '@mdx-js/rollup',
@@ -169,15 +173,25 @@ const react = (_options?: Options): Plugin[] => {
}
},
transformIndexHtml: (_, config) => {
- if (!hmrDisabled) {
+ if (hmrDisabled) return
+ if (isBundledDev) {
return [
{
tag: 'script',
attrs: { type: 'module' },
- children: getPreambleCode(config.server!.config.base),
+ // In bundled dev mode, the src does not go through the middlewares
+ // so we don't need to append the base
+ children: getPreambleCode('/'),
},
]
}
+ return [
+ {
+ tag: 'script',
+ attrs: { type: 'module' },
+ children: getPreambleCode(config.server!.config.base),
+ },
+ ]
},
async transform(code, _id, transformOptions) {
const id = _id.split('?')[0]
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ff4a4784f..91d305a9d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -165,6 +165,25 @@ importers:
specifier: ../../dist
version: link:../../dist
+ packages/plugin-react-swc/playground/bundled-dev:
+ dependencies:
+ react:
+ specifier: ^19.2.7
+ version: 19.2.7
+ react-dom:
+ specifier: ^19.2.7
+ version: 19.2.7(react@19.2.7)
+ devDependencies:
+ '@types/react':
+ specifier: ^19.2.17
+ version: 19.2.17
+ '@types/react-dom':
+ specifier: ^19.2.3
+ version: 19.2.3(@types/react@19.2.17)
+ '@vitejs/plugin-react-swc':
+ specifier: ../../dist
+ version: link:../../dist
+
packages/plugin-react-swc/playground/class-components:
dependencies:
react: