From 5d6ea8efc36bfdcd8b70afa8e82026ad1ccc0a77 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Sat, 2 Apr 2022 22:59:08 +0800 Subject: [PATCH] fix(resolver): skip known ESM entries when resolving a `require` call (#7582) --- .../resolve/__tests__/resolve.spec.ts | 10 ++++++-- packages/playground/resolve/index.html | 20 ++++++++++++---- packages/playground/resolve/package.json | 3 ++- .../dep.cjs | 0 .../index.cjs | 8 +++++++ .../package.json | 2 +- .../require-pkg-with-esm-entries/index.cjs | 9 +++++++ .../require-pkg-with-esm-entries/package.json | 9 +++++++ .../require-pkg-with-module-field/index.cjs | 8 ------- packages/playground/resolve/vite.config.js | 5 +++- packages/vite/src/node/constants.ts | 15 ++++++++++++ packages/vite/src/node/plugins/resolve.ts | 6 +++++ pnpm-lock.yaml | 24 ++++++++++++++++--- 13 files changed, 99 insertions(+), 20 deletions(-) rename packages/playground/resolve/{require-pkg-with-module-field => require-pkg-with-browser-and-module-field}/dep.cjs (100%) create mode 100644 packages/playground/resolve/require-pkg-with-browser-and-module-field/index.cjs rename packages/playground/resolve/{require-pkg-with-module-field => require-pkg-with-browser-and-module-field}/package.json (68%) create mode 100644 packages/playground/resolve/require-pkg-with-esm-entries/index.cjs create mode 100644 packages/playground/resolve/require-pkg-with-esm-entries/package.json delete mode 100644 packages/playground/resolve/require-pkg-with-module-field/index.cjs diff --git a/packages/playground/resolve/__tests__/resolve.spec.ts b/packages/playground/resolve/__tests__/resolve.spec.ts index 2deb2fab7f8d40..46f8f6138b39a4 100644 --- a/packages/playground/resolve/__tests__/resolve.spec.ts +++ b/packages/playground/resolve/__tests__/resolve.spec.ts @@ -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]' ) }) diff --git a/packages/playground/resolve/index.html b/packages/playground/resolve/index.html index 1920ebb675d24c..2478c89b495f49 100644 --- a/packages/playground/resolve/index.html +++ b/packages/playground/resolve/index.html @@ -58,8 +58,17 @@

Resolve file name containing dot

Browser Field

fail

-

Don't resolve to the `module` field if the importer is a `require` call

-

fail

+

+ Resolve to the `browser` field instead of `module` when the importer is a + `require` call +

+

fail

+ +

+ Resolve to the `main` field instead of `module` when the importer is a + `require` call +

+

fail

CSS Entry

@@ -185,8 +194,11 @@

resolve package that contains # in path

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) diff --git a/packages/playground/resolve/package.json b/packages/playground/resolve/package.json index dda4476bc6ae82..4b8d497b3dbb27 100644 --- a/packages/playground/resolve/package.json +++ b/packages/playground/resolve/package.json @@ -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", diff --git a/packages/playground/resolve/require-pkg-with-module-field/dep.cjs b/packages/playground/resolve/require-pkg-with-browser-and-module-field/dep.cjs similarity index 100% rename from packages/playground/resolve/require-pkg-with-module-field/dep.cjs rename to packages/playground/resolve/require-pkg-with-browser-and-module-field/dep.cjs diff --git a/packages/playground/resolve/require-pkg-with-browser-and-module-field/index.cjs b/packages/playground/resolve/require-pkg-with-browser-and-module-field/index.cjs new file mode 100644 index 00000000000000..86d3360ab38dcb --- /dev/null +++ b/packages/playground/resolve/require-pkg-with-browser-and-module-field/index.cjs @@ -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 diff --git a/packages/playground/resolve/require-pkg-with-module-field/package.json b/packages/playground/resolve/require-pkg-with-browser-and-module-field/package.json similarity index 68% rename from packages/playground/resolve/require-pkg-with-module-field/package.json rename to packages/playground/resolve/require-pkg-with-browser-and-module-field/package.json index e409343a7567d5..2a0419b331c407 100644 --- a/packages/playground/resolve/require-pkg-with-module-field/package.json +++ b/packages/playground/resolve/require-pkg-with-browser-and-module-field/package.json @@ -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", diff --git a/packages/playground/resolve/require-pkg-with-esm-entries/index.cjs b/packages/playground/resolve/require-pkg-with-esm-entries/index.cjs new file mode 100644 index 00000000000000..55958fbdba26ee --- /dev/null +++ b/packages/playground/resolve/require-pkg-with-esm-entries/index.cjs @@ -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 diff --git a/packages/playground/resolve/require-pkg-with-esm-entries/package.json b/packages/playground/resolve/require-pkg-with-esm-entries/package.json new file mode 100644 index 00000000000000..b845364bb6f19a --- /dev/null +++ b/packages/playground/resolve/require-pkg-with-esm-entries/package.json @@ -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" + } +} diff --git a/packages/playground/resolve/require-pkg-with-module-field/index.cjs b/packages/playground/resolve/require-pkg-with-module-field/index.cjs deleted file mode 100644 index da215f306d1ac1..00000000000000 --- a/packages/playground/resolve/require-pkg-with-module-field/index.cjs +++ /dev/null @@ -1,8 +0,0 @@ -const dep = require('./dep.cjs') - -const msg = - dep === '1.111222233334444555566e+21' - ? '[success] require-pkg-with-module-field' - : '[failed] require-pkg-with-module-field' - -exports.msg = msg diff --git a/packages/playground/resolve/vite.config.js b/packages/playground/resolve/vite.config.js index 0550d1ecf6f044..c1282f4ffc789d 100644 --- a/packages/playground/resolve/vite.config.js +++ b/packages/playground/resolve/vite.config.js @@ -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' + ] } } diff --git a/packages/vite/src/node/constants.ts b/packages/vite/src/node/constants.ts index 9612cd8c96460d..1741bf2dd7a94b 100644 --- a/packages/vite/src/node/constants.ts +++ b/packages/vite/src/node/constants.ts @@ -6,6 +6,21 @@ export const DEFAULT_MAIN_FIELDS = [ 'jsnext' ] +/** + * A non-exhaustive list of known-to-be-ES-module entry names. + * From + */ +export const KNOWN_ESM_MAIN_FIELDS = [ + 'module', + 'jsnext:main', + 'jsnext', + 'esnext', + 'es2015', + 'es2020', + 'fesm2015', + 'fesm2020' +] + export const DEFAULT_EXTENSIONS = [ '.mjs', '.js', diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 1b59503a9d43ed..10e2989af1114f 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -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' @@ -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 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 461ca065e2e18d..209425cc19d89e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,7 +461,8 @@ importers: '@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 @@ -472,7 +473,8 @@ importers: '@babel/runtime': 7.16.5 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 @@ -504,12 +506,18 @@ importers: packages/playground/resolve/inline-package: specifiers: {} - packages/playground/resolve/require-pkg-with-module-field: + packages/playground/resolve/require-pkg-with-browser-and-module-field: specifiers: bignumber.js: 9.0.2 dependencies: bignumber.js: 9.0.2 + packages/playground/resolve/require-pkg-with-esm-entries: + specifiers: + callbag-from-event: 1.3.0 + dependencies: + callbag-from-event: 1.3.0 + packages/playground/ssr-deps: specifiers: bcrypt: ^5.0.1 @@ -3476,6 +3484,16 @@ packages: get-intrinsic: 1.1.1 dev: true + /callbag-from-event/1.3.0: + resolution: {integrity: sha512-cAu82hKKFmMtKTmd50p/nlMfs1oKz+PGUZmmwhbzPbw4YtjNgTKg6pXjpcQprhBQdrqg/v8pHcAS8Qs6X7r8fw==} + dependencies: + callbag: 1.5.0 + dev: false + + /callbag/1.5.0: + resolution: {integrity: sha512-PH3id0HEb/cNS+BehYlF4Z5wzjKAIUao6ab2hWtMs2bi6aW+0PXl0jymqwnFyT2cQO2h30ggUgpQlmzOpAIKNg==} + dev: false + /callsites/3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'}