From 8909380c355a16e033e79b38246cb65d46bb4db2 Mon Sep 17 00:00:00 2001 From: Brenley Dueck Date: Thu, 17 Sep 2026 20:14:15 -0500 Subject: [PATCH] fix: use the classic JSX runtime for the Vite 8 dep scan (#262) Backport of 3257a97 from next. `jsx: 'preserve'` in optimizeDeps.rolldownOptions.transform was self-defeating: the scanner re-parses the transformed output as plain JS (the js-glob transform force-tags glob-containing modules as moduleType js), so any .tsx with JSX failed with PARSE_ERROR: Unexpected JSX expression, the whole scan aborted and pre-bundling was skipped. The classic runtime lowers JSX to bare React.createElement calls without injecting an import; the scan output is never executed, so the undefined identifier is inert. Verified with a packed tarball against vite 8.3.0 + solid-js 1.9.15: `vite optimize`, the dev server and `vite build` all succeed on a .tsx file that uses import.meta.glob. Co-Authored-By: Claude Fable 5.1 --- .changeset/vite8-scan-jsx-classic.md | 16 ++++++++++++++++ src/index.ts | 11 ++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 .changeset/vite8-scan-jsx-classic.md diff --git a/.changeset/vite8-scan-jsx-classic.md b/.changeset/vite8-scan-jsx-classic.md new file mode 100644 index 0000000..877affa --- /dev/null +++ b/.changeset/vite8-scan-jsx-classic.md @@ -0,0 +1,16 @@ +--- +'vite-plugin-solid': patch +--- + +Vite 8's dependency scan no longer breaks on `.tsx` files (issue #262). +The plugin previously set `optimizeDeps.rolldownOptions.transform.jsx: +'preserve'` to stop Rolldown from injecting `react/jsx-dev-runtime` +imports during the scan — but the scanner re-parses the transformed +output as plain JS (`import.meta.glob` handling force-tags modules as +`js`), so any `.tsx` with JSX was a hard `PARSE_ERROR: Unexpected JSX +expression` that aborted the whole scan and skipped pre-bundling. The +scan transform now uses the classic JSX runtime, which lowers JSX to bare +`React.createElement` calls without injecting any import: the scan output +is never executed, it only exists so rolldown can walk the import graph, +so the undefined identifier is harmless. Backport of the fix already on +the 3.0.0-next line. diff --git a/src/index.ts b/src/index.ts index ead2980..c72c569 100644 --- a/src/index.ts +++ b/src/index.ts @@ -281,10 +281,15 @@ export default function solidPlugin(options: Partial = {}): Plugin { exclude: solidPkgsConfig.optimizeDeps.exclude, // Vite 8+ uses Rolldown for dependency scanning. Rolldown defaults to // React's automatic JSX runtime for .tsx files, injecting a - // react/jsx-dev-runtime import. Tell it to preserve JSX as-is since - // this plugin handles JSX transformation via babel-preset-solid. + // react/jsx-dev-runtime import that fails to resolve and aborts the + // scan. 'preserve' is no fix: the scanner re-parses the transformed + // output as plain JS, so any preserved JSX is a hard parse error + // (issue #262). The classic runtime is the only scan-safe lowering: + // it emits bare `React.createElement` calls without injecting any + // import, and the scan output is never executed — it only exists so + // rolldown can walk the import graph. ...(isVite8OrNewer - ? { rolldownOptions: { transform: { jsx: 'preserve' as const } } } + ? { rolldownOptions: { transform: { jsx: { runtime: 'classic' as const } } } } : {}), }, ...(!isVite6OrNewer ? { ssr: solidPkgsConfig.ssr } : {}),