Skip to content
This repository was archived by the owner on Aug 4, 2021. It is now read-only.

Commit 68f80df

Browse files
keithamuslukastaegert
authored andcommitted
New mainfields option (#182)
* feat: add `mainFields` api. Deprecate `browser`, `jsnext`, `module`, `main` * Fix remaining issues with mainfields * Add new option to types
1 parent 5fa2cf6 commit 68f80df

File tree

5 files changed

+137
-75
lines changed

5 files changed

+137
-75
lines changed

README.md

+13-4
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,33 @@ export default {
2525
},
2626
plugins: [
2727
resolve({
28+
29+
// the fields to scan in a package.json to determine the entry point
30+
// if this list contains "browser", overrides specified in "pkg.browser"
31+
// will be used
32+
mainFields: ['module', 'main'], // Default: ['module', 'main']
33+
34+
// DEPRECATED: use "mainFields" instead
2835
// use "module" field for ES6 module if possible
2936
module: true, // Default: true
3037

38+
// DEPRECATED: use "mainFields" instead
3139
// use "jsnext:main" if possible
3240
// legacy field pointing to ES6 module in third-party libraries,
3341
// deprecated in favor of "pkg.module":
3442
// - see: https://github.com/rollup/rollup/wiki/pkg.module
3543
jsnext: true, // Default: false
3644

45+
// DEPRECATED: use "mainFields" instead
3746
// use "main" field or index.js, even if it's not an ES6 module
3847
// (needs to be converted from CommonJS to ES6)
3948
// – see https://github.com/rollup/rollup-plugin-commonjs
4049
main: true, // Default: true
4150

42-
// some package.json files have a `browser` field which
43-
// specifies alternative files to load for people bundling
44-
// for the browser. If that's you, use this option, otherwise
45-
// pkg.browser will be ignored
51+
// some package.json files have a "browser" field which specifies
52+
// alternative files to load for people bundling for the browser. If
53+
// that's you, either use this option or add "browser" to the
54+
// "mainfields" option, otherwise pkg.browser will be ignored
4655
browser: true, // Default: false
4756

4857
// not all files you want to resolve are .js files

index.d.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1-
import { Plugin } from 'rollup';
2-
import { AsyncOpts } from 'resolve';
1+
import {Plugin} from 'rollup';
2+
import {AsyncOpts} from 'resolve';
33

44
interface RollupNodeResolveOptions {
55
/**
6+
* the fields to scan in a package.json to determine the entry point
7+
* if this list contains "browser", overrides specified in "pkg.browser"
8+
* will be used
9+
* @default ['module', 'main']
10+
*/
11+
mainFields?: ['browser', 'esnext', 'module', 'main'],
12+
/**
13+
* @deprecated use "mainFields" instead
614
* use "module" field for ES6 module if possible
715
* @default true
816
*/
917
module?: boolean;
1018
/**
19+
* @deprecated use "mainFields" instead
1120
* use "jsnext:main" if possible
1221
* legacy field pointing to ES6 module in third-party libraries,
1322
* deprecated in favor of "pkg.module":
@@ -16,17 +25,18 @@ interface RollupNodeResolveOptions {
1625
*/
1726
jsnext?: boolean;
1827
/**
28+
* @deprecated use "mainFields" instead
1929
* use "main" field or index.js, even if it's not an ES6 module
2030
* (needs to be converted from CommonJS to ES6)
2131
* – see https://github.com/rollup/rollup-plugin-commonjs
2232
* @default true
2333
*/
2434
main?: boolean;
2535
/**
26-
* some package.json files have a `browser` field which
27-
* specifies alternative files to load for people bundling
28-
* for the browser. If that's you, use this option, otherwise
29-
* pkg.browser will be ignored
36+
* some package.json files have a "browser" field which specifies
37+
* alternative files to load for people bundling for the browser. If
38+
* that's you, either use this option or add "browser" to the
39+
* "mainfields" option, otherwise pkg.browser will be ignored
3040
* @default false
3141
*/
3242
browser?: boolean;

package-lock.json

+1-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.js

+45-17
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,41 @@ function cachedIsFile (file, cb) {
3737
isFileCache[file].then(contents => cb(null, contents), cb);
3838
}
3939

40+
function getMainFields (options) {
41+
let mainFields;
42+
if (options.mainFields) {
43+
if ('module' in options || 'main' in options || 'jsnext' in options) {
44+
throw new Error(`node-resolve: do not use deprecated 'module', 'main', 'jsnext' options with 'mainFields'`);
45+
}
46+
mainFields = options.mainFields;
47+
} else {
48+
mainFields = ['module', 'main'];
49+
[['module', 'module'], ['jsnext', 'jsnext:main'], ['main', 'main']].forEach(([option, field]) => {
50+
if (option in options) {
51+
// eslint-disable-next-line no-console
52+
console.warn(`node-resolve: setting options.${option} is deprecated, please override options.mainFields instead`);
53+
if (options[option] === false) {
54+
mainFields = mainFields.filter(mainField => mainField === field);
55+
} else if (options[option] === true && mainFields.indexOf(field) === -1) {
56+
mainFields.push(field);
57+
}
58+
}
59+
});
60+
}
61+
if (options.browser && mainFields.indexOf('browser') === -1) {
62+
return ['browser'].concat(mainFields);
63+
}
64+
if ( !mainFields.length ) {
65+
throw new Error( `Please ensure at least one 'mainFields' value is specified` );
66+
}
67+
return mainFields;
68+
}
69+
4070
const resolveIdAsync = (file, opts) => new Promise((fulfil, reject) => resolveId(file, opts, (err, contents) => err ? reject(err) : fulfil(contents)));
4171

4272
export default function nodeResolve ( options = {} ) {
43-
const useModule = options.module !== false;
44-
const useMain = options.main !== false;
45-
const useJsnext = options.jsnext === true;
73+
const mainFields = getMainFields(options);
74+
const useBrowserOverrides = mainFields.indexOf('browser') !== -1;
4675
const isPreferBuiltinsSet = options.preferBuiltins === true || options.preferBuiltins === false;
4776
const preferBuiltins = isPreferBuiltinsSet ? options.preferBuiltins : true;
4877
const customResolveOptions = options.customResolveOptions || {};
@@ -59,10 +88,6 @@ export default function nodeResolve ( options = {} ) {
5988
throw new Error( 'options.skip is no longer supported — you should use the main Rollup `external` option instead' );
6089
}
6190

62-
if ( !useModule && !useMain && !useJsnext ) {
63-
throw new Error( `At least one of options.module, options.main or options.jsnext must be true` );
64-
}
65-
6691
let preserveSymlinks;
6792

6893
return {
@@ -83,7 +108,7 @@ export default function nodeResolve ( options = {} ) {
83108
const basedir = importer ? dirname( importer ) : process.cwd();
84109

85110
// https://github.com/defunctzombie/package-browser-field-spec
86-
if (options.browser && browserMapCache[importer]) {
111+
if (useBrowserOverrides && browserMapCache[importer]) {
87112
const resolvedImportee = resolve( basedir, importee );
88113
const browser = browserMapCache[importer];
89114
if (browser[importee] === false || browser[resolvedImportee] === false) {
@@ -115,7 +140,7 @@ export default function nodeResolve ( options = {} ) {
115140
basedir,
116141
packageFilter ( pkg, pkgPath ) {
117142
const pkgRoot = dirname( pkgPath );
118-
if (options.browser && typeof pkg[ 'browser' ] === 'object') {
143+
if (useBrowserOverrides && typeof pkg[ 'browser' ] === 'object') {
119144
packageBrowserField = Object.keys(pkg[ 'browser' ]).reduce((browser, key) => {
120145
let resolved = pkg[ 'browser' ][ key ];
121146
if (resolved && resolved[0] === '.') {
@@ -136,13 +161,16 @@ export default function nodeResolve ( options = {} ) {
136161
}, {});
137162
}
138163

139-
if (options.browser && typeof pkg[ 'browser' ] === 'string') {
140-
pkg[ 'main' ] = pkg[ 'browser' ];
141-
} else if ( useModule && pkg[ 'module' ] ) {
142-
pkg[ 'main' ] = pkg[ 'module' ];
143-
} else if ( useJsnext && pkg[ 'jsnext:main' ] ) {
144-
pkg[ 'main' ] = pkg[ 'jsnext:main' ];
145-
} else if ( ( useJsnext || useModule ) && !useMain ) {
164+
let overriddenMain = false;
165+
for ( let i = 0; i < mainFields.length; i++ ) {
166+
const field = mainFields[i];
167+
if ( typeof pkg[ field ] === 'string' ) {
168+
pkg[ 'main' ] = pkg[ field ];
169+
overriddenMain = true;
170+
break;
171+
}
172+
}
173+
if ( overriddenMain === false && mainFields.indexOf( 'main' ) === -1 ) {
146174
disregardResult = true;
147175
}
148176
return pkg;
@@ -161,7 +189,7 @@ export default function nodeResolve ( options = {} ) {
161189
Object.assign( resolveOptions, customResolveOptions )
162190
)
163191
.then(resolved => {
164-
if ( resolved && options.browser && packageBrowserField ) {
192+
if ( resolved && useBrowserOverrides && packageBrowserField ) {
165193
if ( packageBrowserField.hasOwnProperty(resolved) ) {
166194
if (!packageBrowserField[resolved]) {
167195
browserMapCache[resolved] = packageBrowserField;

0 commit comments

Comments
 (0)