diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index d3672e81c71fe4..1d7c86a301d2b1 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -648,13 +648,36 @@ export function tryNodeResolve( basedir = nestedResolveFrom(nestedRoot, basedir, preserveSymlinks) } + // nearest package.json + let nearestPkg: PackageData | undefined + // nearest package.json that may have the `exports` field let pkg: PackageData | undefined - const pkgId = possiblePkgIds.reverse().find((pkgId) => { - pkg = resolvePackageData(pkgId, basedir, preserveSymlinks, packageCache)! - return pkg + + let pkgId = possiblePkgIds.reverse().find((pkgId) => { + nearestPkg = resolvePackageData( + pkgId, + basedir, + preserveSymlinks, + packageCache + )! + return nearestPkg })! - if (!pkg) { + const rootPkgId = possiblePkgIds[0] + const rootPkg = resolvePackageData( + rootPkgId, + basedir, + preserveSymlinks, + packageCache + )! + if (rootPkg?.data?.exports) { + pkg = rootPkg + pkgId = rootPkgId + } else { + pkg = nearestPkg + } + + if (!pkg || !nearestPkg) { // 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 ( @@ -753,7 +776,8 @@ export function tryNodeResolve( } const ext = path.extname(resolved) - const isCJS = ext === '.cjs' || (ext === '.js' && pkg.data.type !== 'module') + const isCJS = + ext === '.cjs' || (ext === '.js' && nearestPkg.data.type !== 'module') if ( !options.ssrOptimizeCheck && diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index 0e4e163570a575..b5b9c98b0336d0 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -126,7 +126,7 @@ async function instantiateModule( preserveSymlinks, isBuild: true, isProduction, - isRequire: true, + isRequire: false, root } diff --git a/playground/resolve/__tests__/resolve.spec.ts b/playground/resolve/__tests__/resolve.spec.ts index 6d7a9b6efb1907..8f910f4989bfaa 100644 --- a/playground/resolve/__tests__/resolve.spec.ts +++ b/playground/resolve/__tests__/resolve.spec.ts @@ -36,6 +36,13 @@ test('deep import with exports field + mapped dir', async () => { ) }) +// this is how Svelte 3 is packaged +test('deep import with exports and legacy fallback', async () => { + expect(await page.textContent('.exports-legacy-fallback')).toMatch( + '[success]' + ) +}) + test('Respect exports field env key priority', async () => { expect(await page.textContent('.exports-env')).toMatch('[success]') }) diff --git a/playground/resolve/exports-legacy-fallback/dir/index.js b/playground/resolve/exports-legacy-fallback/dir/index.js new file mode 100644 index 00000000000000..9c02b83a60f172 --- /dev/null +++ b/playground/resolve/exports-legacy-fallback/dir/index.js @@ -0,0 +1 @@ +export const msg = '[fail] mapped js file' diff --git a/playground/resolve/exports-legacy-fallback/dir/index.mjs b/playground/resolve/exports-legacy-fallback/dir/index.mjs new file mode 100644 index 00000000000000..fa498c78684744 --- /dev/null +++ b/playground/resolve/exports-legacy-fallback/dir/index.mjs @@ -0,0 +1 @@ +export const msg = '[success] mapped mjs file' diff --git a/playground/resolve/exports-legacy-fallback/dir/package.json b/playground/resolve/exports-legacy-fallback/dir/package.json new file mode 100644 index 00000000000000..4cf44a46cb30d2 --- /dev/null +++ b/playground/resolve/exports-legacy-fallback/dir/package.json @@ -0,0 +1,4 @@ +{ + "main": "index.js", + "module": "index.mjs" +} diff --git a/playground/resolve/exports-legacy-fallback/index.js b/playground/resolve/exports-legacy-fallback/index.js new file mode 100644 index 00000000000000..03677be8580ef6 --- /dev/null +++ b/playground/resolve/exports-legacy-fallback/index.js @@ -0,0 +1 @@ +export default 5 diff --git a/playground/resolve/exports-legacy-fallback/package.json b/playground/resolve/exports-legacy-fallback/package.json new file mode 100644 index 00000000000000..9934531a2d45ae --- /dev/null +++ b/playground/resolve/exports-legacy-fallback/package.json @@ -0,0 +1,12 @@ +{ + "name": "resolve-exports-legacy-fallback", + "private": true, + "version": "1.0.0", + "exports": { + "./dir": { + "import": "./dir/index.mjs", + "require": "./dir/index.js" + }, + ".": "index.js" + } +} diff --git a/playground/resolve/index.html b/playground/resolve/index.html index c744d4b9317463..6150dc86dbb1ef 100644 --- a/playground/resolve/index.html +++ b/playground/resolve/index.html @@ -24,6 +24,9 @@

Deep import with exports field + mapped directory

Exports field env priority

fail

+

Exports with legacy fallback

+

fail

+

Resolve /index.*

fail

@@ -163,6 +166,9 @@

resolve package that contains # in path

import { msg as exportsEnvMsg } from 'resolve-exports-env' text('.exports-env', exportsEnvMsg) + import { msg as exportsLegacyFallbackMsg } from 'resolve-exports-legacy-fallback/dir' + text('.exports-legacy-fallback', exportsLegacyFallbackMsg) + // implicit index resolving import { foo } from './util' text('.index', foo()) diff --git a/playground/resolve/package.json b/playground/resolve/package.json index 760fba0c02f5a0..a7f4966360d19c 100644 --- a/playground/resolve/package.json +++ b/playground/resolve/package.json @@ -20,6 +20,7 @@ "resolve-custom-condition": "link:./custom-condition", "resolve-custom-main-field": "link:./custom-main-field", "resolve-exports-env": "link:./exports-env", + "resolve-exports-legacy-fallback": "link:./exports-legacy-fallback", "resolve-exports-path": "link:./exports-path", "resolve-linked": "workspace:*" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c17bb951e931c..713af3da8d2bb1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -896,6 +896,7 @@ importers: resolve-custom-condition: link:./custom-condition resolve-custom-main-field: link:./custom-main-field resolve-exports-env: link:./exports-env + resolve-exports-legacy-fallback: link:./exports-legacy-fallback resolve-exports-path: link:./exports-path resolve-linked: workspace:* dependencies: @@ -910,6 +911,7 @@ importers: resolve-custom-condition: link:custom-condition resolve-custom-main-field: link:custom-main-field resolve-exports-env: link:exports-env + resolve-exports-legacy-fallback: link:exports-legacy-fallback resolve-exports-path: link:exports-path resolve-linked: link:../resolve-linked @@ -940,6 +942,12 @@ importers: playground/resolve/exports-env: specifiers: {} + playground/resolve/exports-legacy-fallback: + specifiers: {} + + playground/resolve/exports-legacy-fallback/dir: + specifiers: {} + playground/resolve/exports-path: specifiers: {}