diff --git a/packages/node-resolve/README.md b/packages/node-resolve/README.md index 5993f3089..24738f24e 100755 --- a/packages/node-resolve/README.md +++ b/packages/node-resolve/README.md @@ -64,7 +64,7 @@ Setting this option will add extra conditions on top of the default conditions. Type: `Boolean`
Default: `false` -If `true`, instructs the plugin to use the `"browser"` property in `package.json` files to specify alternative files to load for bundling. This is useful when bundling for a browser environment. Alternatively, a value of `'browser'` can be added to the `mainFields` option. If `false`, any `"browser"` properties in package files will be ignored. This option takes precedence over `mainFields`. +If `true`, instructs the plugin to use the `"browser"` property in `package.json` files to specify alternative files to load for bundling. This is useful when bundling for a browser environment. Alternatively, a value of `'browser'` can be added to the `mainFields` option. If `false`, any `"browser"` properties in package files will be ignored. This option takes precedence over `mainFields`. In addition, if `"browser"` is not present in `exportConditions`, it will be appended so that browser conditionals in `"exports"` will also apply. > This option does not work when a package is using [package entrypoints](https://nodejs.org/api/packages.html#packages_package_entry_points) diff --git a/packages/node-resolve/src/index.js b/packages/node-resolve/src/index.js index a1861864b..d9a88eef9 100644 --- a/packages/node-resolve/src/index.js +++ b/packages/node-resolve/src/index.js @@ -189,6 +189,9 @@ export function nodeResolve(opts = {}) { const isRequire = opts && opts.custom && opts.custom['node-resolve'] && opts.custom['node-resolve'].isRequire; const exportConditions = isRequire ? conditionsCjs : conditionsEsm; + + if (useBrowserOverrides && !exportConditions.includes('browser')) + exportConditions.push('browser'); const resolvedWithoutBuiltins = await resolveImportSpecifiers({ importer, diff --git a/packages/node-resolve/src/package/resolvePackageTarget.js b/packages/node-resolve/src/package/resolvePackageTarget.js index 47ead33d5..fbc98769d 100644 --- a/packages/node-resolve/src/package/resolvePackageTarget.js +++ b/packages/node-resolve/src/package/resolvePackageTarget.js @@ -10,6 +10,24 @@ function includesInvalidSegments(pathSegments, moduleDirs) { .some((t) => ['.', '..', ...moduleDirs].includes(t)); } +async function resolvePackageTargetBrowserMapped(context, { target, subpath, pattern, internal }) { + const resolvedTarget = await resolvePackageTarget(context, { + target, + subpath, + pattern, + internal + }); + if ( + resolvedTarget && + resolvedTarget.startsWith('./') && + context.packageBrowserField && + context.packageBrowserField[resolvedTarget] + ) { + return context.packageBrowserField[resolvedTarget]; + } + return resolvedTarget; +} + async function resolvePackageTarget(context, { target, subpath, pattern, internal }) { if (typeof target === 'string') { if (!pattern && subpath.length > 0 && !target.endsWith('/')) { @@ -24,11 +42,11 @@ async function resolvePackageTarget(context, { target, subpath, pattern, interna target.replace(/\*/g, subpath), context.pkgURL.href ); - return result ? pathToFileURL(result.location) : null; + return result ? pathToFileURL(result.location).href : null; } const result = await context.resolveId(`${target}${subpath}`, context.pkgURL.href); - return result ? pathToFileURL(result.location) : null; + return result ? pathToFileURL(result.location).href : null; } throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`); } @@ -111,4 +129,4 @@ async function resolvePackageTarget(context, { target, subpath, pattern, interna throw new InvalidPackageTargetError(context, `Invalid exports field.`); } -export default resolvePackageTarget; +export default resolvePackageTargetBrowserMapped; diff --git a/packages/node-resolve/test/browser.js b/packages/node-resolve/test/browser.js index 69a63dfe7..a3ba91392 100644 --- a/packages/node-resolve/test/browser.js +++ b/packages/node-resolve/test/browser.js @@ -199,3 +199,23 @@ test('pkg.browser with mapping to prevent bundle by specifying a value of false' t.is(module.exports, 'ok'); }); + +test('exports.browser can be mapped via pkg.browser', async (t) => { + const bundle = await rollup({ + input: 'browser-exports-browser-browser.js', + plugins: [nodeResolve({ browser: true }), commonjs()] + }); + const { module } = await testBundle(t, bundle); + + t.is(module.exports, 'browser'); +}); + +test('exports.browser does not take precedence over export map result, when browser:false', async (t) => { + const bundle = await rollup({ + input: 'browser-exports-browser.js', + plugins: [nodeResolve(), commonjs()] + }); + const { module } = await testBundle(t, bundle); + + t.is(module.exports, 'require'); +}); diff --git a/packages/node-resolve/test/fixtures/browser-exports-browser-browser.js b/packages/node-resolve/test/fixtures/browser-exports-browser-browser.js new file mode 100644 index 000000000..0b51c17a2 --- /dev/null +++ b/packages/node-resolve/test/fixtures/browser-exports-browser-browser.js @@ -0,0 +1,3 @@ +import b from 'exports-browser-browser'; + +module.exports = b; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/browser-exports-browser.js b/packages/node-resolve/test/fixtures/browser-exports-browser.js new file mode 100644 index 000000000..44a0586d1 --- /dev/null +++ b/packages/node-resolve/test/fixtures/browser-exports-browser.js @@ -0,0 +1,3 @@ +const b = require('exports-browser'); + +module.exports = b; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/browser-override-exports.js b/packages/node-resolve/test/fixtures/browser-override-exports.js new file mode 100644 index 000000000..b7b9f6716 --- /dev/null +++ b/packages/node-resolve/test/fixtures/browser-override-exports.js @@ -0,0 +1,3 @@ +const Nanoid = require('nanoid'); + +module.exports = Nanoid; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/browser.js b/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/browser.js new file mode 100644 index 000000000..e36fe2f1b --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/browser.js @@ -0,0 +1 @@ +module.exports = 'browser'; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/index.js b/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/index.js new file mode 100644 index 000000000..cde7d6391 --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/index.js @@ -0,0 +1 @@ +module.exports = "index"; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/package.json b/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/package.json new file mode 100644 index 000000000..d079dff29 --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/package.json @@ -0,0 +1,13 @@ +{ + "main": "index.cjs", + "module": "index.js", + "browser": { + "./index.js": "./browser.js" + }, + "exports": { + ".": { + "browser": "./index.js", + "require": "./require.js" + } + } +} \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/require.js b/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/require.js new file mode 100644 index 000000000..b7275c575 --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser-browser/require.js @@ -0,0 +1 @@ +module.exports = 'require'; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser/browser.js b/packages/node-resolve/test/fixtures/node_modules/exports-browser/browser.js new file mode 100644 index 000000000..e36fe2f1b --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser/browser.js @@ -0,0 +1 @@ +module.exports = 'browser'; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser/ignored-browser.js b/packages/node-resolve/test/fixtures/node_modules/exports-browser/ignored-browser.js new file mode 100644 index 000000000..62f993f21 --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser/ignored-browser.js @@ -0,0 +1 @@ +module.exports = 'ignored-browser'; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser/import.js b/packages/node-resolve/test/fixtures/node_modules/exports-browser/import.js new file mode 100644 index 000000000..eb2b60d6f --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser/import.js @@ -0,0 +1 @@ +module.exports = 'import'; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser/package.json b/packages/node-resolve/test/fixtures/node_modules/exports-browser/package.json new file mode 100644 index 000000000..21e9ac225 --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser/package.json @@ -0,0 +1,8 @@ +{ + "main": "index.cjs", + "module": "index.js", + "browser": { + "./require.js": "./ignored-browser.js" + }, + "exports": "./require.js" +} \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/exports-browser/require.js b/packages/node-resolve/test/fixtures/node_modules/exports-browser/require.js new file mode 100644 index 000000000..b7275c575 --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/exports-browser/require.js @@ -0,0 +1 @@ +module.exports = 'require'; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/nanoid/index.cjs b/packages/node-resolve/test/fixtures/node_modules/nanoid/index.cjs new file mode 100644 index 000000000..68356d181 --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/nanoid/index.cjs @@ -0,0 +1 @@ +module.exports = 'node'; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/nanoid/index.js b/packages/node-resolve/test/fixtures/node_modules/nanoid/index.js new file mode 100644 index 000000000..e36fe2f1b --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/nanoid/index.js @@ -0,0 +1 @@ +module.exports = 'browser'; \ No newline at end of file diff --git a/packages/node-resolve/test/fixtures/node_modules/nanoid/package.json b/packages/node-resolve/test/fixtures/node_modules/nanoid/package.json new file mode 100644 index 000000000..098d7552e --- /dev/null +++ b/packages/node-resolve/test/fixtures/node_modules/nanoid/package.json @@ -0,0 +1,11 @@ +{ + "browser": { + "./index.cjs": "./index.js" + }, + "exports": { + ".": { + "require": "./index.cjs", + "import": "./index.js" + } + } +} \ No newline at end of file