From d6f85c287f247d68c541077f0db4b403cef63114 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 11 Aug 2025 13:19:34 +0900 Subject: [PATCH 1/3] fix(rsc): replace `?v=` check with more robust `node_modules` detection --- packages/plugin-rsc/src/plugin.ts | 10 ++++++---- packages/plugin-rsc/src/plugins/utils.ts | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index 7bba9b1a..386e1ed4 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -32,7 +32,11 @@ import { } from './transforms' import { generateEncryptionKey, toBase64 } from './utils/encryption-utils' import { createRpcServer } from './utils/rpc' -import { normalizeViteImportAnalysisUrl, prepareError } from './vite-utils' +import { + cleanUrl, + normalizeViteImportAnalysisUrl, + prepareError, +} from './vite-utils' import { cjsModuleRunnerPlugin } from './plugins/cjs' import { evalValue, parseIdQuery } from './plugins/utils' @@ -978,9 +982,7 @@ function vitePluginUseClient( `[vite-rsc] detected an internal client boundary created by a package imported on rsc environment`, ) } - importId = `/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/${encodeURIComponent( - id.split('?v=')[0]!, - )}` + importId = `/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/${encodeURIComponent(cleanUrl(id))}` referenceKey = importId } else if (packageSource) { if (this.environment.mode === 'dev') { diff --git a/packages/plugin-rsc/src/plugins/utils.ts b/packages/plugin-rsc/src/plugins/utils.ts index 5628fad5..a544a58e 100644 --- a/packages/plugin-rsc/src/plugins/utils.ts +++ b/packages/plugin-rsc/src/plugins/utils.ts @@ -19,3 +19,9 @@ export function parseIdQuery(id: string): { const query = Object.fromEntries(new URLSearchParams(rawQuery)) return { filename, query } } + +// https://github.com/vitejs/vite/blob/946831f986cb797009b8178659d2b31f570c44ff/packages/vite/src/shared/utils.ts#L31-L34 +const postfixRE = /[?#].*$/ +export function cleanUrl(url: string): string { + return url.replace(postfixRE, '') +} From ce1da35edd9dcd176933d959624132ca9dd3687b Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 11 Aug 2025 13:42:35 +0900 Subject: [PATCH 2/3] fix: check /node_modules/ instead of `?v=` --- packages/plugin-rsc/src/plugin.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index 386e1ed4..c8a00dd0 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -963,9 +963,9 @@ function vitePluginUseClient( let importId: string let referenceKey: string const packageSource = packageSources.get(id) - if (!packageSource && id.includes('?v=')) { + if (!packageSource && id.includes('/node_modules/')) { assert(this.environment.mode === 'dev') - // If non package source `?v=` reached here, this is a client boundary + // If non package source reached here (often with ?v=... query), this is a client boundary // created by a package imported on server environment, which breaks the // expectation on dependency optimizer on browser. Directly copying over // "?v=" from client optimizer in client reference can make a hashed @@ -1225,7 +1225,7 @@ function vitePluginUseServer( let normalizedId_: string | undefined const getNormalizedId = () => { if (!normalizedId_) { - if (id.includes('?v=')) { + if (id.includes('/node_modules/')) { assert(this.environment.mode === 'dev') const ignored = useServerPluginOptions.ignoredPackageWarnings?.some( @@ -1240,8 +1240,8 @@ function vitePluginUseServer( ) } // module runner has additional resolution step and it's not strict about - // module identity of `import(id)` like browser, so we simply strip it off. - id = id.split('?v=')[0]! + // module identity of `import(id)` like browser, so we simply strip queries such as `?v=`. + id = cleanUrl(id) } if (config.command === 'build') { normalizedId_ = hashString(path.relative(config.root, id)) From a4174cea632528aa057e67b28db773d831356109 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 11 Aug 2025 13:46:54 +0900 Subject: [PATCH 3/3] fix: check dev --- packages/plugin-rsc/src/plugin.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index c8a00dd0..1181c7d1 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -963,8 +963,11 @@ function vitePluginUseClient( let importId: string let referenceKey: string const packageSource = packageSources.get(id) - if (!packageSource && id.includes('/node_modules/')) { - assert(this.environment.mode === 'dev') + if ( + !packageSource && + this.environment.mode === 'dev' && + id.includes('/node_modules/') + ) { // If non package source reached here (often with ?v=... query), this is a client boundary // created by a package imported on server environment, which breaks the // expectation on dependency optimizer on browser. Directly copying over @@ -1225,8 +1228,10 @@ function vitePluginUseServer( let normalizedId_: string | undefined const getNormalizedId = () => { if (!normalizedId_) { - if (id.includes('/node_modules/')) { - assert(this.environment.mode === 'dev') + if ( + this.environment.mode === 'dev' && + id.includes('/node_modules/') + ) { const ignored = useServerPluginOptions.ignoredPackageWarnings?.some( (pattern) =>