diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 4cdd2043cc41b7..f8b909276b08f2 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -19,6 +19,7 @@ import { bareImportRE, cleanUrl, createDebugger, + deepImportRE, ensureVolumeInPath, fsPathFromId, getPotentialTsSrcPaths, @@ -663,32 +664,12 @@ export function tryNodeResolve( ): PartialResolvedId | undefined { const { root, dedupe, isBuild, preserveSymlinks, packageCache } = options - const possiblePkgIds: string[] = [] - for (let prevSlashIndex = -1; ; ) { - let slashIndex = id.indexOf('/', prevSlashIndex + 1) - if (slashIndex < 0) { - slashIndex = id.length - } - - const part = id.slice(prevSlashIndex + 1, (prevSlashIndex = slashIndex)) - if (!part) { - break - } - - // Assume path parts with an extension are not package roots, except for the - // first path part (since periods are sadly allowed in package names). - // At the same time, skip the first path part if it begins with "@" - // (since "@foo/bar" should be treated as the top-level path). - if (possiblePkgIds.length ? path.extname(part) : part[0] === '@') { - continue - } - - const possiblePkgId = id.slice(0, slashIndex) - possiblePkgIds.push(possiblePkgId) - } + // check for deep import, e.g. "my-lib/foo" + const deepMatch = id.match(deepImportRE) + const pkgId = deepMatch ? deepMatch[1] || deepMatch[2] : id let basedir: string - if (dedupe?.some((id) => possiblePkgIds.includes(id))) { + if (dedupe?.includes(pkgId)) { basedir = root } else if ( importer && @@ -700,39 +681,8 @@ export function tryNodeResolve( basedir = root } - let pkg: PackageData | undefined - let pkgId: string | undefined - // nearest package.json - let nearestPkg: PackageData | undefined - - const rootPkgId = possiblePkgIds[0] - - const rootPkg = resolvePackageData( - rootPkgId, - basedir, - preserveSymlinks, - packageCache, - )! - - const nearestPkgId = [...possiblePkgIds].reverse().find((pkgId) => { - nearestPkg = resolvePackageData( - pkgId, - basedir, - preserveSymlinks, - packageCache, - )! - return nearestPkg - })! - - if (rootPkg?.data?.exports) { - pkgId = rootPkgId - pkg = rootPkg - } else { - pkgId = nearestPkgId - pkg = nearestPkg - } - - if (!pkg || !nearestPkg) { + const pkg = resolvePackageData(pkgId, basedir, preserveSymlinks, packageCache) + if (!pkg) { // if import can't be found, check if it's an optional peer dep. // if so, we can resolve to a special id that errors only when imported. if ( @@ -760,13 +710,8 @@ export function tryNodeResolve( return } - let resolveId = resolvePackageEntry - let unresolvedId = pkgId - const isDeepImport = unresolvedId !== id - if (isDeepImport) { - resolveId = resolveDeepImport - unresolvedId = '.' + id.slice(pkgId.length) - } + const resolveId = deepMatch ? resolveDeepImport : resolvePackageEntry + const unresolvedId = deepMatch ? '.' + id.slice(pkgId.length) : pkgId let resolved: string | undefined try { @@ -807,14 +752,10 @@ export function tryNodeResolve( return resolved } let resolvedId = id - if (isDeepImport) { - if (!pkg?.data.exports && path.extname(id) !== resolvedExt) { - resolvedId = resolved.id.slice(resolved.id.indexOf(id)) - isDebug && - debug( - `[processResult] ${colors.cyan(id)} -> ${colors.dim(resolvedId)}`, - ) - } + if (deepMatch && !pkg?.data.exports && path.extname(id) !== resolvedExt) { + resolvedId = resolved.id.slice(resolved.id.indexOf(id)) + isDebug && + debug(`[processResult] ${colors.cyan(id)} -> ${colors.dim(resolvedId)}`) } return { ...resolved, id: resolvedId, external: true } } @@ -831,8 +772,6 @@ export function tryNodeResolve( } const ext = path.extname(resolved) - const isCJS = - ext === '.cjs' || (ext === '.js' && nearestPkg.data.type !== 'module') if ( !options.ssrOptimizeCheck && @@ -867,7 +806,12 @@ export function tryNodeResolve( // The only optimized deps are the ones explicitly listed in the config. (!options.ssrOptimizeCheck && !isBuild && ssr) || // Only optimize non-external CJS deps during SSR by default - (ssr && !isCJS && !(include?.includes(pkgId) || include?.includes(id))) + (ssr && + !( + ext === '.cjs' || + (ext === '.js' && resolvePkg(resolved, options)?.data.type !== 'module') + ) && + !(include?.includes(pkgId) || include?.includes(id))) if (options.ssrOptimizeCheck) { return {