Skip to content

Commit

Permalink
fix(resolve): respect exports env key order
Browse files Browse the repository at this point in the history
fix #1418
  • Loading branch information
yyx990803 committed Jan 7, 2021
1 parent 9eab790 commit b58c860
Show file tree
Hide file tree
Showing 14 changed files with 84 additions and 45 deletions.
4 changes: 4 additions & 0 deletions packages/playground/resolve/__tests__/resolve.spec.ts
Expand Up @@ -22,6 +22,10 @@ test('deep import with exports field + mapped dir', async () => {
)
})

test('Respect exports field env key priority', async () => {
expect(await page.textContent('.exports-env')).toMatch('[success]')
})

test('omitted index/*', async () => {
expect(await page.textContent('.index')).toMatch('[success]')
})
Expand Down
1 change: 1 addition & 0 deletions packages/playground/resolve/exports-env/browser.js
@@ -0,0 +1 @@
export const msg = 'fail (browser.js)'
1 change: 1 addition & 0 deletions packages/playground/resolve/exports-env/browser.mjs
@@ -0,0 +1 @@
export const msg = '[success] exports env (browser.mjs)'
1 change: 1 addition & 0 deletions packages/playground/resolve/exports-env/fallback.umd.js
@@ -0,0 +1 @@
export const msg = 'fail (fallback.umd.js)'
11 changes: 11 additions & 0 deletions packages/playground/resolve/exports-env/package.json
@@ -0,0 +1,11 @@
{
"name": "resolve-exports-env",
"version": "1.0.0",
"exports": {
"import": {
"browser": "./browser.mjs"
},
"browser": "./browser.js",
"default": "./fallback.umd.js"
}
}
@@ -1,5 +1,5 @@
{
"name": "resolve-conditional-exports",
"name": "resolve-exports-path",
"version": "1.0.0",
"exports": {
".": {
Expand Down
14 changes: 10 additions & 4 deletions packages/playground/resolve/index.html
Expand Up @@ -15,6 +15,9 @@ <h2>Deep import with exports field + exposed directory</h2>
<h2>Deep import with exports field + mapped directory</h2>
<p class="exports-deep-mapped-dir">fail</p>

<h2>Exports field env priority</h2>
<p class="exports-env">fail</p>

<h2>Resolve /index.*</h2>
<p class="index">fail</p>

Expand Down Expand Up @@ -56,21 +59,24 @@ <h2>Inline package</h2>
))

// exports field
import { msg } from 'resolve-conditional-exports'
import { msg } from 'resolve-exports-path'
text('.exports-entry', msg)

// deep import w/ exports
import { msg as deepMsg } from 'resolve-conditional-exports/deep.js'
import { msg as deepMsg } from 'resolve-exports-path/deep.js'
text('.exports-deep', deepMsg)

// deep import w/ exposed dir
import { msg as exposedDirMsg } from 'resolve-conditional-exports/dir/dir'
import { msg as exposedDirMsg } from 'resolve-exports-path/dir/dir'
text('.exports-deep-exposed-dir', exposedDirMsg)

// deep import w/ mapped dir
import { msg as mappedDirMsg } from 'resolve-conditional-exports/dir-mapped/dir'
import { msg as mappedDirMsg } from 'resolve-exports-path/dir-mapped/dir'
text('.exports-deep-mapped-dir', mappedDirMsg)

import { msg as exportsEnvMsg } from 'resolve-exports-env'
text('.exports-env', exportsEnvMsg)

// implicit index resolving
import { foo } from './util'
text('.index', foo())
Expand Down
3 changes: 2 additions & 1 deletion packages/playground/resolve/package.json
Expand Up @@ -8,7 +8,8 @@
"debug": "node --inspect-brk ../../vite/bin/vite"
},
"dependencies": {
"resolve-conditional-exports": "link:./conditional-exports",
"resolve-exports-path": "link:./exports-path",
"resolve-exports-env": "link:./exports-env",
"resolve-browser-field": "link:./browser-field",
"@babel/runtime": "^7.12.5",
"normalize.css": "^8.0.1"
Expand Down
80 changes: 45 additions & 35 deletions packages/vite/src/node/plugins/resolve.ts
Expand Up @@ -381,17 +381,7 @@ export function resolvePackageEntry(
// https://nodejs.org/api/packages.html#packages_package_entry_points
const { exports: exportsField } = data
if (exportsField) {
if (typeof exportsField === 'string') {
entryPoint = exportsField
} else if (Array.isArray(exportsField)) {
entryPoint = exportsField[0]
} else if (isObject(exportsField)) {
if ('.' in exportsField) {
entryPoint = resolveConditionalExports(exportsField['.'])
} else {
entryPoint = resolveConditionalExports(exportsField)
}
}
entryPoint = resolveConditionalExports(exportsField, '.')
}
}

Expand Down Expand Up @@ -439,24 +429,13 @@ function resolveDeepImport(

// map relative based on exports data
if (exportsField) {
let isExported = false
if (isObject(exportsField) && !Array.isArray(exportsField)) {
if (relativeId in exportsField) {
relativeId = resolveConditionalExports(exportsField[relativeId])
isExported = true
} else {
for (const key in exportsField) {
if (key.endsWith('/') && relativeId.startsWith(key)) {
// directory mapping
const replacement = resolveConditionalExports(exportsField[key])
relativeId = replacement && relativeId.replace(key, replacement)
isExported = true
break
}
}
}
relativeId = resolveConditionalExports(exportsField, relativeId)
} else {
// not exposed
relativeId = undefined
}
if (!isExported || !relativeId) {
if (!relativeId) {
throw new Error(
`Package subpath '${relativeId}' is not defined by "exports" in ` +
`${path.join(dir, 'package.json')}.`
Expand All @@ -481,20 +460,51 @@ function resolveDeepImport(
}
}

function resolveConditionalExports(exp: any): string | undefined {
const ENV_KEYS = [
'esmodules',
'import',
'module',
'require',
'browser',
'node',
'default'
]

function resolveConditionalExports(exp: any, id: string): string | undefined {
if (typeof exp === 'string') {
return exp
} else if (isObject(exp)) {
if (typeof exp.browser === 'string') {
return exp.browser
} else if (typeof exp.import === 'string') {
return exp.import
} else if (typeof exp.default === 'string') {
return exp.default
let isFileListing: boolean | undefined
let fallback: string | undefined
for (const key in exp) {
if (isFileListing === undefined) {
isFileListing = key[0] === '.'
}
if (isFileListing) {
if (key === id) {
return resolveConditionalExports(exp[key], id)
} else if (key.endsWith('/') && id.startsWith(key)) {
// mapped directory
const replacement = resolveConditionalExports(exp[key], id)
return replacement && id.replace(key, replacement)
}
} else if (ENV_KEYS.includes(key)) {
// https://github.com/vitejs/vite/issues/1418
// respect env key order
// but intentionally de-prioritize "require" and "default" keys
if (key === 'require' || key === 'default') {
if (!fallback) fallback = key
} else {
return resolveConditionalExports(exp[key], id)
}
}
if (fallback) {
return resolveConditionalExports(exp[key], id)
}
}
} else if (Array.isArray(exp)) {
for (let i = 0; i < exp.length; i++) {
const res = resolveConditionalExports(exp[i])
const res = resolveConditionalExports(exp[i], id)
if (res) return res
}
}
Expand Down
12 changes: 8 additions & 4 deletions yarn.lock
Expand Up @@ -7067,17 +7067,21 @@ requires-port@^1.0.0:
version "0.0.0"
uid ""

"resolve-conditional-exports@link:./packages/playground/resolve/conditional-exports":
version "0.0.0"
uid ""

resolve-cwd@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
dependencies:
resolve-from "^5.0.0"

"resolve-exports-env@link:./packages/playground/resolve/exports-env":
version "0.0.0"
uid ""

"resolve-exports-path@link:./packages/playground/resolve/exports-path":
version "0.0.0"
uid ""

resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
Expand Down

0 comments on commit b58c860

Please sign in to comment.