From 78eb59abfeb96fcc44e3678c643dff06ceceec29 Mon Sep 17 00:00:00 2001 From: Santhi Prakash Date: Fri, 21 Aug 2026 09:51:57 +0000 Subject: [PATCH] fix(optimizer): serve optimized deps on hash mismatch instead of 504 The 504 throw in optimizedDepsPlugin.load fired whenever the browserHash embedded in a lazy-route wrapper no longer matched the current dep browserHash. For dynamic imports the browser had already initiated the request with the wrapper's hash, so the 504 surfaced as 'Failed to fetch dynamically imported module' (issue #22303). The optimizer still triggers a full reload when its output actually changes, so serving the current chunk is safe: the subsequent reload re-issues the request with the new hash. We keep the catch-branch throw for the case where the file is genuinely missing on disk. --- .../vite/src/node/plugins/optimizedDeps.ts | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/packages/vite/src/node/plugins/optimizedDeps.ts b/packages/vite/src/node/plugins/optimizedDeps.ts index 972e93fa9a1e6f..edd9bed61839d2 100644 --- a/packages/vite/src/node/plugins/optimizedDeps.ts +++ b/packages/vite/src/node/plugins/optimizedDeps.ts @@ -53,13 +53,6 @@ export function optimizedDepsPlugin(): Plugin { // Search in both the currently optimized and newly discovered deps const info = optimizedDepInfoFromFile(metadata, file) if (info) { - if ( - browserHash && - info.browserHash !== browserHash && - !environment.config.optimizeDeps.ignoreOutdatedRequests - ) { - throwOutdatedRequest(id) - } try { // This is an entry point, it may still not be bundled await info.processing @@ -69,17 +62,15 @@ export function optimizedDepsPlugin(): Plugin { // returns an empty response that will error. throwProcessingError(id) } - const newMetadata = depsOptimizer.metadata - if (metadata !== newMetadata) { - const currentInfo = optimizedDepInfoFromFile(newMetadata!, file) - if ( - info.browserHash !== currentInfo?.browserHash && - !environment.config.optimizeDeps.ignoreOutdatedRequests - ) { - throwOutdatedRequest(id) - } - } } + // We do not throw on `?v=` mismatch here. The browser may have started + // a dynamic import for an optimized dep using the browserHash that was + // baked into the wrapper when it was transformed, before the optimizer + // had a chance to commit a new batch with a different hash. Throwing + // 504 in that case breaks the in-flight import with + // `Failed to fetch dynamically imported module`. Instead, serve the + // current chunk: the optimizer triggers a full reload when its output + // actually changes, which re-issues the request with the new hash. debug?.(`load ${colors.cyan(file)}`) // Load the file from the cache instead of waiting for other plugin // load hooks to avoid race conditions, once processing is resolved,