Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix(resolver): skip known ESM entries when resolving a require call (
  • Loading branch information
sodatea committed Apr 2, 2022
1 parent a74bd7b commit 5d6ea8e
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 20 deletions.
10 changes: 8 additions & 2 deletions packages/playground/resolve/__tests__/resolve.spec.ts
Expand Up @@ -61,8 +61,14 @@ test('dont add extension to directory name (./dir-with-ext.js/index.js)', async
expect(await page.textContent('.dir-with-ext')).toMatch('[success]')
})

test('do not resolve to the `module` field if the importer is a `require` call', async () => {
expect(await page.textContent('.require-pkg-with-module-field')).toMatch(
test('resolve to the `browser` field instead of `module` when the importer is a `require` call', async () => {
expect(
await page.textContent('.require-pkg-with-browser-and-module-field')
).toMatch('[success]')
})

test('resolve to the `main` field instead of `module` when the importer is a `require` call', async () => {
expect(await page.textContent('.require-pkg-with-esm-entries')).toMatch(
'[success]'
)
})
Expand Down
20 changes: 16 additions & 4 deletions packages/playground/resolve/index.html
Expand Up @@ -58,8 +58,17 @@ <h2>Resolve file name containing dot</h2>
<h2>Browser Field</h2>
<p class="browser">fail</p>

<h2>Don't resolve to the `module` field if the importer is a `require` call</h2>
<p class="require-pkg-with-module-field">fail</p>
<h2>
Resolve to the `browser` field instead of `module` when the importer is a
`require` call
</h2>
<p class="require-pkg-with-browser-and-module-field">fail</p>

<h2>
Resolve to the `main` field instead of `module` when the importer is a
`require` call
</h2>
<p class="require-pkg-with-esm-entries">fail</p>

<h2>CSS Entry</h2>
<p class="css"></p>
Expand Down Expand Up @@ -185,8 +194,11 @@ <h2>resolve package that contains # in path</h2>
text('.browser', main)
}

import { msg as requireButWithModuleFieldMsg } from 'require-pkg-with-module-field'
text('.require-pkg-with-module-field', requireButWithModuleFieldMsg)
import { msg as requireBrowserMsg } from 'require-pkg-with-browser-and-module-field'
text('.require-pkg-with-browser-and-module-field', requireBrowserMsg)

import { msg as requireMainMsg } from 'require-pkg-with-esm-entries'
text('.require-pkg-with-esm-entries', requireMainMsg)

import { msg as customExtMsg } from './custom-ext'
text('.custom-ext', customExtMsg)
Expand Down
3 changes: 2 additions & 1 deletion packages/playground/resolve/package.json
Expand Up @@ -12,7 +12,8 @@
"@babel/runtime": "^7.16.0",
"es5-ext": "0.10.53",
"normalize.css": "^8.0.1",
"require-pkg-with-module-field": "link:./require-pkg-with-module-field",
"require-pkg-with-browser-and-module-field": "link:./require-pkg-with-browser-and-module-field",
"require-pkg-with-esm-entries": "link:./require-pkg-with-esm-entries",
"resolve-browser-field": "link:./browser-field",
"resolve-custom-condition": "link:./custom-condition",
"resolve-custom-main-field": "link:./custom-main-field",
Expand Down
@@ -0,0 +1,8 @@
const dep = require('./dep.cjs')

const msg =
dep === '1.111222233334444555566e+21'
? '[success] require-pkg-with-browser-and-module-field'
: '[failed] require-pkg-with-browser-and-module-field'

exports.msg = msg
@@ -1,5 +1,5 @@
{
"name": "require-pkg-with-module-field",
"name": "require-pkg-with-browser-and-module-field",
"private": true,
"version": "1.0.0",
"main": "./index.cjs",
Expand Down
@@ -0,0 +1,9 @@
const fromEvent = require('callbag-from-event')

const msg =
// should be the exported function instead of the ES Module record (`{ default: ... }`)
typeof fromEvent === 'function'
? '[success] require-pkg-with-esm-entries'
: '[failed] require-pkg-with-esm-entries'

exports.msg = msg
@@ -0,0 +1,9 @@
{
"name": "require-pkg-with-esm-entries",
"private": true,
"version": "1.0.0",
"main": "./index.cjs",
"dependencies": {
"callbag-from-event": "1.3.0"
}
}

This file was deleted.

5 changes: 4 additions & 1 deletion packages/playground/resolve/vite.config.js
Expand Up @@ -42,6 +42,9 @@ module.exports = {
}
],
optimizeDeps: {
include: ['require-pkg-with-module-field']
include: [
'require-pkg-with-browser-and-module-field',
'require-pkg-with-esm-entries'
]
}
}
15 changes: 15 additions & 0 deletions packages/vite/src/node/constants.ts
Expand Up @@ -6,6 +6,21 @@ export const DEFAULT_MAIN_FIELDS = [
'jsnext'
]

/**
* A non-exhaustive list of known-to-be-ES-module entry names.
* From <https://github.com/stereobooster/package.json#package-bundlers>
*/
export const KNOWN_ESM_MAIN_FIELDS = [
'module',
'jsnext:main',
'jsnext',
'esnext',
'es2015',
'es2020',
'fesm2015',
'fesm2020'
]

export const DEFAULT_EXTENSIONS = [
'.mjs',
'.js',
Expand Down
6 changes: 6 additions & 0 deletions packages/vite/src/node/plugins/resolve.ts
Expand Up @@ -7,6 +7,7 @@ import {
SPECIAL_QUERY_RE,
DEFAULT_EXTENSIONS,
DEFAULT_MAIN_FIELDS,
KNOWN_ESM_MAIN_FIELDS,
OPTIMIZABLE_ENTRY_RE,
DEP_VERSION_RE
} from '../constants'
Expand Down Expand Up @@ -777,6 +778,11 @@ export function resolvePackageEntry(

if (!entryPoint || entryPoint.endsWith('.mjs')) {
for (const field of options.mainFields || DEFAULT_MAIN_FIELDS) {
// If the initiator is a `require` call, don't use the ESM entries
if (options.isRequire && KNOWN_ESM_MAIN_FIELDS.includes(field)) {
continue
}

if (typeof data[field] === 'string') {
entryPoint = data[field]
break
Expand Down
24 changes: 21 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5d6ea8e

Please sign in to comment.