Skip to content

Commit 691e432

Browse files
authored
fix(resolve): ensure exports has precedence over mainFields (cherry pick #11234) (#11595)
1 parent 167753d commit 691e432

File tree

8 files changed

+35
-1
lines changed

8 files changed

+35
-1
lines changed

packages/vite/src/node/plugins/resolve.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,8 @@ export function resolvePackageEntry(
945945
entryPoint = resolveExports(data, '.', options, targetWeb)
946946
}
947947

948+
const resolvedFromExports = !!entryPoint
949+
948950
// if exports resolved to .mjs, still resolve other fields.
949951
// This is because .mjs files can technically import .cjs files which would
950952
// make them invalid for pure ESM environments - so if other module/browser
@@ -994,7 +996,9 @@ export function resolvePackageEntry(
994996
}
995997
}
996998

997-
if (!entryPoint || entryPoint.endsWith('.mjs')) {
999+
// fallback to mainFields if still not resolved
1000+
// TODO: review if `.mjs` check is still needed
1001+
if (!resolvedFromExports && (!entryPoint || entryPoint.endsWith('.mjs'))) {
9981002
for (const field of options.mainFields) {
9991003
if (field === 'browser') continue // already checked above
10001004
if (typeof data[field] === 'string') {

playground/resolve/__tests__/resolve.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ test('Respect production/development conditionals', async () => {
6363
)
6464
})
6565

66+
test('Respect exports to take precedence over mainFields', async () => {
67+
expect(await page.textContent('.exports-with-module')).toMatch('[success]')
68+
})
69+
6670
test('implicit dir/index.js', async () => {
6771
expect(await page.textContent('.index')).toMatch('[success]')
6872
})
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// import.mjs should take precedence
2+
export const msg = '[success] exports with module (import.mjs)'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// import.mjs should take precedence
2+
export const msg = '[fail] exports with module (module.mjs)'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@vitejs/test-resolve-exports-with-module",
3+
"private": true,
4+
"version": "1.0.0",
5+
"type": "commonjs",
6+
"module": "./module.mjs",
7+
"exports": {
8+
"import": "./import.mjs"
9+
}
10+
}

playground/resolve/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ <h2>Exports field read only from the root package.json</h2>
3333
<h2>Exports with legacy fallback</h2>
3434
<p class="exports-legacy-fallback">fail</p>
3535

36+
<h2>Exports with module</h2>
37+
<p class="exports-with-module">fail</p>
38+
3639
<h2>Resolve /index.*</h2>
3740
<p class="index">fail</p>
3841

@@ -181,6 +184,9 @@ <h2>resolve package that contains # in path</h2>
181184
import { msg as exportsLegacyFallbackMsg } from '@vitejs/test-resolve-exports-legacy-fallback/dir'
182185
text('.exports-legacy-fallback', exportsLegacyFallbackMsg)
183186

187+
import { msg as exportsWithModule } from '@vitejs/test-resolve-exports-with-module'
188+
text('.exports-with-module', exportsWithModule)
189+
184190
// implicit index resolving
185191
import { foo } from './util'
186192
text('.index', foo())

playground/resolve/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@vitejs/test-resolve-exports-from-root": "link:./exports-from-root",
2525
"@vitejs/test-resolve-exports-legacy-fallback": "link:./exports-legacy-fallback",
2626
"@vitejs/test-resolve-exports-path": "link:./exports-path",
27+
"@vitejs/test-resolve-exports-with-module": "link:./exports-with-module",
2728
"@vitejs/test-resolve-linked": "workspace:*"
2829
}
2930
}

pnpm-lock.yaml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)