Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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()
})
2 changes: 2 additions & 0 deletions packages/plugin-react-swc/playground/bundled-dev/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<div id="app"></div>
<script type="module" src="./src/main.tsx"></script>
20 changes: 20 additions & 0 deletions packages/plugin-react-swc/playground/bundled-dev/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
14 changes: 14 additions & 0 deletions packages/plugin-react-swc/playground/bundled-dev/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useState } from 'react'

export default function App() {
const [count, setCount] = useState(0)

return (
<>
<h1>Hello Vite + React</h1>
<button id="state-button" onClick={() => setCount((count) => count + 1)}>
count is: {count}
</button>
</>
)
}
4 changes: 4 additions & 0 deletions packages/plugin-react-swc/playground/bundled-dev/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import ReactDOM from 'react-dom/client'
import App from './App.tsx'

ReactDOM.createRoot(document.getElementById('app')!).render(<App />)
23 changes: 23 additions & 0 deletions packages/plugin-react-swc/playground/bundled-dev/tsconfig.json
Original file line number Diff line number Diff line change
@@ -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
}
}
11 changes: 11 additions & 0 deletions packages/plugin-react-swc/playground/bundled-dev/vite.config.ts
Original file line number Diff line number Diff line change
@@ -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()],
})
18 changes: 16 additions & 2 deletions packages/plugin-react-swc/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand All @@ -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]
Expand Down
19 changes: 19 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.