Describe the bug
This is a Vite bug that affects Vitest.
vite:html-inline-proxy plugin is supposed to resolve requests for module scripts from index.html, but it fails to do so in some environments. The issue is that this plugin expects URL to include ?html-proxy, but in some cases the URL instead includes ?v=12535af4&html-proxy, causing regex to not match, and thus request fails to resolve correctly. See Explanation section below for more details.
Reproduction
https://github.com/maxpatiiuk/vite-html-proxy-bug
Steps to reproduce
-
Clone this repository
git clone https://github.com/maxpatiiuk/vite-html-proxy-bug
cd vite-html-proxy-bug
-
Install dependencies
-
Run vitest browser mode
See the following error message in the terminal:
10:42:08 AM [vite] Pre-transform error: Failed to parse source for import analysis because the content contains invalid JS syntax. You may need to install appropriate plugins to handle the .js file format, or if it's an asset, add "**/*.js" to `assetsInclude` in your configuration.
10:42:08 AM [vite] Internal server error: Failed to parse source for import analysis because the content contains invalid JS syntax. You may need to install appropriate plugins to handle the .js file format, or if it's an asset, add "**/*.js" to `assetsInclude` in your configuration.
Plugin: vite:import-analysis
File: /Users/mak13180/site/esri/vite-html-proxy-bug/node_modules/@vitest/browser/dist/client/tester/tester.html?v=0aab3063&html-proxy&index=0.js:7:41
5 | <link rel="icon" href="proxy.php?url=https%3A%2F%2Fredirect.github.com%2F%7B__VITEST_FAVICON__%7D" type="image/svg+xml">
6 | <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 | <title>Vitest Browser Tester</title>
| ^
8 | <script type="module" crossorigin src="proxy.php?url=https%3A%2F%2Fredirect.github.com%2F__vitest_browser__%2Ftester-B8eJg1-s.js"></script>
9 | <link rel="modulepreload" crossorigin href="proxy.php?url=https%3A%2F%2Fredirect.github.com%2F__vitest_browser__%2Futils-CaCTRFti.js">
at TransformPluginContext._formatError (file:///Users/mak13180/site/esri/vite-html-proxy-bug/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:49255:41)
at TransformPluginContext.error (file:///Users/mak13180/site/esri/vite-html-proxy-bug/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:49250:16)
at TransformPluginContext.transform (file:///Users/mak13180/site/esri/vite-html-proxy-bug/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:63993:14)
at async PluginContainer.transform (file:///Users/mak13180/site/esri/vite-html-proxy-bug/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:49096:18)
at async loadAndTransform (file:///Users/mak13180/site/esri/vite-html-proxy-bug/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:51929:27)
at async viteTransformMiddleware (file:///Users/mak13180/site/esri/vite-html-proxy-bug/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:61881:24)
Explanation
Starting with Vitest 2.1.5, Vitest browser mode calls transformIndexHtml.
If html contains module scripts, preTransformRequest will be called:
|
preTransformRequest(server!, modulePath, decodedBase) |
The request URL may look like /Users/mak13180/site/esri/arcgis-dashboards/node_modules/@vitest/browser/dist/client/tester/tester.html?html-proxy&index=0.js
Later, ensureVersionQuery is called to add version hash to query string:
|
return ensureVersionQuery(res, id, options, depsOptimizer) |
The updated URL: /Users/mak13180/site/esri/arcgis-dashboards/node_modules/@vitest/browser/dist/client/tester/tester.html?v=12535af4&html-proxy&index=0.js
Such URL is supposed to be resolved by the vite:html-inline-proxy plugin:
|
name: 'vite:html-inline-proxy', |
|
|
|
resolveId(id) { |
|
if (isHTMLProxy(id)) { |
|
return id |
|
} |
|
}, |
|
|
|
load(id) { |
|
const proxyMatch = htmlProxyRE.exec(id) |
|
if (proxyMatch) { |
, however,
that does not work.
Here is the bug: the regex that checks for html-proxy URLs expects the URL to contain ?html-proxy, where as the above URL contains &html-proxy:
|
const htmlProxyRE = |
|
/\?html-proxy=?(?:&inline-css)?(?:&style-attr)?&index=(\d+)\.(?:js|css)$/ |
.
Because of that, pluginContainer.load(id) fails to resolve the file. In such cases, it falls back to reading the file from the file system:
|
code = await fsp.readFile(file, 'utf-8') |
fs.readFile() ignores the query string, reads the tester.html file, and serves it - however, the .js file was expected. This causes an error in the Pre-transform during import analysis.
Solution
Vite should update the following regexes:
|
const htmlProxyRE = |
|
/\?html-proxy=?(?:&inline-css)?(?:&style-attr)?&index=(\d+)\.(?:js|css)$/ |
|
const isHtmlProxyRE = /\?html-proxy\b/ |
Should replace \? by [?&].
For reference, this is already correct in the vite:css-post plugin:
|
const htmlProxyRE = /[?&]html-proxy\b/ |
.
Also, the Vite team should evaluate whether this bug affects any other Vite plugins.
System Info
System:
OS: macOS 15.2
CPU: (10) arm64 Apple M1 Pro
Memory: 702.52 MB / 32.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.12.0 - ~/.local/state/fnm_multishells/98022_1737052578656/bin/node
Yarn: 1.22.19 - ~/.local/state/fnm_multishells/98022_1737052578656/bin/yarn
npm: 10.9.0 - ~/.local/state/fnm_multishells/98022_1737052578656/bin/npm
pnpm: 8.9.0 - ~/.local/state/fnm_multishells/98022_1737052578656/bin/pnpm
Browsers:
Chrome: 131.0.6778.265
Safari: 18.2
npmPackages:
vite: ^5.2.0 => 5.4.11
Reproducible in `@vitest/browser` in 2.1.5 and above including 3.0.0 (related commit: https://github.com/vitest-dev/vitest/commit/169028f03abf5e80d77924f4ed9ae6107647c4c0). Not reproducible in 2.1.3 as transformIndexHtml wasn't called in that version.
Reproducible with Playwright and default provider in headless and headed mode in Chrome and Chromium. Reproducible with yarn monorepo and npm.
Used Package Manager
npm
Logs
Click to expand!
Too large for github. File log.log
Validations
Describe the bug
This is a Vite bug that affects Vitest.
vite:html-inline-proxyplugin is supposed to resolve requests for module scripts from index.html, but it fails to do so in some environments. The issue is that this plugin expects URL to include?html-proxy, but in some cases the URL instead includes?v=12535af4&html-proxy, causing regex to not match, and thus request fails to resolve correctly. SeeExplanationsection below for more details.Reproduction
https://github.com/maxpatiiuk/vite-html-proxy-bug
Steps to reproduce
Clone this repository
git clone https://github.com/maxpatiiuk/vite-html-proxy-bug cd vite-html-proxy-bugInstall dependencies
Run vitest browser mode
See the following error message in the terminal:
Explanation
Starting with Vitest 2.1.5, Vitest browser mode calls transformIndexHtml.
If html contains module scripts,
preTransformRequestwill be called:vite/packages/vite/src/node/server/middlewares/indexHtml.ts
Line 257 in 4f5845a
The request URL may look like
/Users/mak13180/site/esri/arcgis-dashboards/node_modules/@vitest/browser/dist/client/tester/tester.html?html-proxy&index=0.jsLater,
ensureVersionQueryis called to add version hash to query string:vite/packages/vite/src/node/plugins/resolve.ts
Line 277 in 4f5845a
The updated URL:
/Users/mak13180/site/esri/arcgis-dashboards/node_modules/@vitest/browser/dist/client/tester/tester.html?v=12535af4&html-proxy&index=0.jsSuch URL is supposed to be resolved by the
vite:html-inline-proxyplugin:vite/packages/vite/src/node/plugins/html.ts
Lines 96 to 106 in 4f5845a
Here is the bug: the regex that checks for html-proxy URLs expects the URL to contain
?html-proxy, where as the above URL contains&html-proxy:vite/packages/vite/src/node/plugins/html.ts
Lines 52 to 53 in 4f5845a
Because of that,
pluginContainer.load(id)fails to resolve the file. In such cases, it falls back to reading the file from the file system:vite/packages/vite/src/node/server/transformRequest.ts
Line 276 in 4f5845a
fs.readFile()ignores the query string, reads thetester.htmlfile, and serves it - however, the .js file was expected. This causes an error in the Pre-transform during import analysis.Solution
Vite should update the following regexes:
vite/packages/vite/src/node/plugins/html.ts
Lines 52 to 54 in 4f5845a
Should replace
\?by[?&].For reference, this is already correct in the
vite:css-postplugin:vite/packages/vite/src/node/plugins/css.ts
Line 227 in 4f5845a
Also, the Vite team should evaluate whether this bug affects any other Vite plugins.
System Info
System: OS: macOS 15.2 CPU: (10) arm64 Apple M1 Pro Memory: 702.52 MB / 32.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 22.12.0 - ~/.local/state/fnm_multishells/98022_1737052578656/bin/node Yarn: 1.22.19 - ~/.local/state/fnm_multishells/98022_1737052578656/bin/yarn npm: 10.9.0 - ~/.local/state/fnm_multishells/98022_1737052578656/bin/npm pnpm: 8.9.0 - ~/.local/state/fnm_multishells/98022_1737052578656/bin/pnpm Browsers: Chrome: 131.0.6778.265 Safari: 18.2 npmPackages: vite: ^5.2.0 => 5.4.11 Reproducible in `@vitest/browser` in 2.1.5 and above including 3.0.0 (related commit: https://github.com/vitest-dev/vitest/commit/169028f03abf5e80d77924f4ed9ae6107647c4c0). Not reproducible in 2.1.3 as transformIndexHtml wasn't called in that version. Reproducible with Playwright and default provider in headless and headed mode in Chrome and Chromium. Reproducible with yarn monorepo and npm.Used Package Manager
npm
Logs
Click to expand!
Too large for github. File log.log
Validations