From ba3047d56270211c1aee7bcf8372b33654c0e54b Mon Sep 17 00:00:00 2001 From: patak Date: Thu, 10 Mar 2022 15:55:59 +0100 Subject: [PATCH] fix: needs es interop check for newly discovered deps (#7243) --- packages/vite/src/node/optimizer/index.ts | 41 +++++++++++++++++-- .../src/node/optimizer/registerMissing.ts | 12 ++++-- .../vite/src/node/plugins/importAnalysis.ts | 33 +++++++++------ .../vite/src/node/plugins/optimizedDeps.ts | 27 ++---------- 4 files changed, 69 insertions(+), 44 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index ef32fe97b47203..36d08bdc654040 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -300,10 +300,7 @@ export async function createOptimizeDepsRun( // server is running deps = depsFromOptimizedDepInfo(newDeps) - // Clone optimized info objects, fileHash, browserHash may be changed for them - for (const o of Object.keys(newDeps)) { - metadata.optimized[o] = { ...newDeps[o] } - } + metadata.optimized = newDeps // update global browser hash, but keep newDeps individual hashs until we know // if files are stable so we can avoid a full page reload @@ -738,3 +735,39 @@ function getDepHash(root: string, config: ResolvedConfig): string { ) return createHash('sha256').update(content).digest('hex').substring(0, 8) } + +export function optimizeDepInfoFromFile( + metadata: DepOptimizationMetadata, + file: string +): OptimizedDepInfo | undefined { + return ( + findFileInfo(metadata.optimized, file) || + findFileInfo(metadata.discovered, file) + ) +} + +function findFileInfo( + dependenciesInfo: Record, + file: string +): OptimizedDepInfo | undefined { + for (const o of Object.keys(dependenciesInfo)) { + const info = dependenciesInfo[o] + if (info.file === file) { + return info + } + } +} + +export async function optimizedDepNeedsInterop( + metadata: DepOptimizationMetadata, + file: string +): Promise { + const depInfo = optimizeDepInfoFromFile(metadata, file) + + if (!depInfo) return undefined + + // Wait until the dependency has been pre-bundled + await depInfo.processing + + return depInfo?.needsInterop +} diff --git a/packages/vite/src/node/optimizer/registerMissing.ts b/packages/vite/src/node/optimizer/registerMissing.ts index cdc9e8006c1f52..2b7fe0bb8c629c 100644 --- a/packages/vite/src/node/optimizer/registerMissing.ts +++ b/packages/vite/src/node/optimizer/registerMissing.ts @@ -79,7 +79,14 @@ export function createMissingImporterRegisterFn( // All deps, previous known and newly discovered are rebundled, // respect insertion order to keep the metadata file stable - const newDeps = { ...metadata.optimized, ...metadata.discovered } + + // Clone optimized info objects, fileHash, browserHash may be changed for them + const clonedOptimizedDeps: Record = {} + for (const o of Object.keys(metadata.optimized)) { + clonedOptimizedDeps[o] = { ...metadata.optimized[o] } + } + + const newDeps = { ...clonedOptimizedDeps, ...metadata.discovered } const thisDepOptimizationProcessing = depOptimizationProcessing // Other rerun will await until this run is finished @@ -119,9 +126,8 @@ export function createMissingImporterRegisterFn( // While optimizeDeps is running, new missing deps may be discovered, // in which case they will keep being added to metadata.discovered for (const o of Object.keys(metadata.discovered)) { - if (!newData.optimized[o] && !newData.discovered[o]) { + if (!newData.optimized[o]) { newData.discovered[o] = metadata.discovered[o] - delete metadata.discovered[o] } } newData.processing = thisDepOptimizationProcessing.promise diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 121b5e61714171..f9d50b13e1885e 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -49,7 +49,8 @@ import { transformRequest } from '../server/transformRequest' import { isOptimizedDepFile, createIsOptimizedDepUrl, - getDepsCacheDir + getDepsCacheDir, + optimizedDepNeedsInterop } from '../optimizer' const isDebug = !!process.env.DEBUG @@ -433,24 +434,30 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // rewrite if (url !== specifier) { let rewriteDone = false - if (isOptimizedDepFile(resolvedId, config)) { - // for optimized cjs deps, support named imports by rewriting named - // imports to const assignments. - const optimizeDepsMetadata = server._optimizeDepsMetadata! - const { optimized } = optimizeDepsMetadata + if ( + isOptimizedDepFile(resolvedId, config) && + !resolvedId.match(optimizedDepChunkRE) + ) { + // for optimized cjs deps, support named imports by rewriting named imports to const assignments. + // internal optimized chunks don't need es interop and are excluded // The browserHash in resolvedId could be stale in which case there will be a full // page reload. We could return a 404 in that case but it is safe to return the request const file = cleanUrl(resolvedId) // Remove ?v={hash} - const dep = Object.keys(optimized).find( - (k) => optimized[k].file === file - ) - // Wait until the dependency has been pre-bundled - dep && (await optimized[dep].processing) + const needsInterop = await optimizedDepNeedsInterop( + server._optimizeDepsMetadata!, + file + ) - if (dep && optimized[dep].needsInterop) { - debug(`${dep} needs interop`) + if (needsInterop === undefined) { + config.logger.error( + colors.red( + `Vite Error, ${url} optimized info should be defined` + ) + ) + } else if (needsInterop) { + debug(`${url} needs interop`) if (isDynamicImport) { // rewrite `import('package')` to expose the default directly str().overwrite( diff --git a/packages/vite/src/node/plugins/optimizedDeps.ts b/packages/vite/src/node/plugins/optimizedDeps.ts index c7e03927cf6574..8fbdca8d08905f 100644 --- a/packages/vite/src/node/plugins/optimizedDeps.ts +++ b/packages/vite/src/node/plugins/optimizedDeps.ts @@ -3,8 +3,7 @@ import type { Plugin } from '../plugin' import colors from 'picocolors' import { DEP_VERSION_RE } from '../constants' import { cleanUrl, createDebugger } from '../utils' -import { isOptimizedDepFile } from '../optimizer' -import type { DepOptimizationMetadata, OptimizedDepInfo } from '../optimizer' +import { isOptimizedDepFile, optimizeDepInfoFromFile } from '../optimizer' import type { ViteDevServer } from '..' export const ERR_OPTIMIZE_DEPS_PROCESSING_ERROR = @@ -33,6 +32,8 @@ export function optimizedDepsPlugin(): Plugin { const browserHash = versionMatch ? versionMatch[1].split('=')[1] : undefined + + // Search in both the currently optimized and newly discovered deps const info = optimizeDepInfoFromFile(metadata, file) if (info) { if (browserHash && info.browserHash !== browserHash) { @@ -93,25 +94,3 @@ function throwOutdatedRequest(id: string) { // send a 504 status code request timeout throw err } - -function optimizeDepInfoFromFile( - metadata: DepOptimizationMetadata, - file: string -): OptimizedDepInfo | undefined { - return ( - findFileInfo(metadata.optimized, file) || - findFileInfo(metadata.discovered, file) - ) -} - -function findFileInfo( - dependenciesInfo: Record, - file: string -): OptimizedDepInfo | undefined { - for (const o of Object.keys(dependenciesInfo)) { - const info = dependenciesInfo[o] - if (info.file === file) { - return info - } - } -}