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

Commit

Permalink
New mainfields option (#182)
Browse files Browse the repository at this point in the history
* feat: add `mainFields` api. Deprecate `browser`, `jsnext`, `module`, `main`

* Fix remaining issues with mainfields

* Add new option to types
  • Loading branch information
keithamus authored and lukastaegert committed Apr 6, 2019
1 parent 5fa2cf6 commit 68f80df
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 75 deletions.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,33 @@ export default {
},
plugins: [
resolve({

// the fields to scan in a package.json to determine the entry point
// if this list contains "browser", overrides specified in "pkg.browser"
// will be used
mainFields: ['module', 'main'], // Default: ['module', 'main']

// DEPRECATED: use "mainFields" instead
// use "module" field for ES6 module if possible
module: true, // Default: true

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

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

// some package.json files have a `browser` field which
// specifies alternative files to load for people bundling
// for the browser. If that's you, use this option, otherwise
// pkg.browser will be ignored
// some package.json files have a "browser" field which specifies
// alternative files to load for people bundling for the browser. If
// that's you, either use this option or add "browser" to the
// "mainfields" option, otherwise pkg.browser will be ignored
browser: true, // Default: false

// not all files you want to resolve are .js files
Expand Down
22 changes: 16 additions & 6 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { Plugin } from 'rollup';
import { AsyncOpts } from 'resolve';
import {Plugin} from 'rollup';
import {AsyncOpts} from 'resolve';

interface RollupNodeResolveOptions {
/**
* the fields to scan in a package.json to determine the entry point
* if this list contains "browser", overrides specified in "pkg.browser"
* will be used
* @default ['module', 'main']
*/
mainFields?: ['browser', 'esnext', 'module', 'main'],
/**
* @deprecated use "mainFields" instead
* use "module" field for ES6 module if possible
* @default true
*/
module?: boolean;
/**
* @deprecated use "mainFields" instead
* use "jsnext:main" if possible
* legacy field pointing to ES6 module in third-party libraries,
* deprecated in favor of "pkg.module":
Expand All @@ -16,17 +25,18 @@ interface RollupNodeResolveOptions {
*/
jsnext?: boolean;
/**
* @deprecated use "mainFields" instead
* use "main" field or index.js, even if it's not an ES6 module
* (needs to be converted from CommonJS to ES6)
* – see https://github.com/rollup/rollup-plugin-commonjs
* @default true
*/
main?: boolean;
/**
* some package.json files have a `browser` field which
* specifies alternative files to load for people bundling
* for the browser. If that's you, use this option, otherwise
* pkg.browser will be ignored
* some package.json files have a "browser" field which specifies
* alternative files to load for people bundling for the browser. If
* that's you, either use this option or add "browser" to the
* "mainfields" option, otherwise pkg.browser will be ignored
* @default false
*/
browser?: boolean;
Expand Down
3 changes: 1 addition & 2 deletions package-lock.json

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

62 changes: 45 additions & 17 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,41 @@ function cachedIsFile (file, cb) {
isFileCache[file].then(contents => cb(null, contents), cb);
}

function getMainFields (options) {
let mainFields;
if (options.mainFields) {
if ('module' in options || 'main' in options || 'jsnext' in options) {
throw new Error(`node-resolve: do not use deprecated 'module', 'main', 'jsnext' options with 'mainFields'`);
}
mainFields = options.mainFields;
} else {
mainFields = ['module', 'main'];
[['module', 'module'], ['jsnext', 'jsnext:main'], ['main', 'main']].forEach(([option, field]) => {
if (option in options) {
// eslint-disable-next-line no-console
console.warn(`node-resolve: setting options.${option} is deprecated, please override options.mainFields instead`);
if (options[option] === false) {
mainFields = mainFields.filter(mainField => mainField === field);
} else if (options[option] === true && mainFields.indexOf(field) === -1) {
mainFields.push(field);
}
}
});
}
if (options.browser && mainFields.indexOf('browser') === -1) {
return ['browser'].concat(mainFields);
}
if ( !mainFields.length ) {
throw new Error( `Please ensure at least one 'mainFields' value is specified` );
}
return mainFields;
}

const resolveIdAsync = (file, opts) => new Promise((fulfil, reject) => resolveId(file, opts, (err, contents) => err ? reject(err) : fulfil(contents)));

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

if ( !useModule && !useMain && !useJsnext ) {
throw new Error( `At least one of options.module, options.main or options.jsnext must be true` );
}

let preserveSymlinks;

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

// https://github.com/defunctzombie/package-browser-field-spec
if (options.browser && browserMapCache[importer]) {
if (useBrowserOverrides && browserMapCache[importer]) {
const resolvedImportee = resolve( basedir, importee );
const browser = browserMapCache[importer];
if (browser[importee] === false || browser[resolvedImportee] === false) {
Expand Down Expand Up @@ -115,7 +140,7 @@ export default function nodeResolve ( options = {} ) {
basedir,
packageFilter ( pkg, pkgPath ) {
const pkgRoot = dirname( pkgPath );
if (options.browser && typeof pkg[ 'browser' ] === 'object') {
if (useBrowserOverrides && typeof pkg[ 'browser' ] === 'object') {
packageBrowserField = Object.keys(pkg[ 'browser' ]).reduce((browser, key) => {
let resolved = pkg[ 'browser' ][ key ];
if (resolved && resolved[0] === '.') {
Expand All @@ -136,13 +161,16 @@ export default function nodeResolve ( options = {} ) {
}, {});
}

if (options.browser && typeof pkg[ 'browser' ] === 'string') {
pkg[ 'main' ] = pkg[ 'browser' ];
} else if ( useModule && pkg[ 'module' ] ) {
pkg[ 'main' ] = pkg[ 'module' ];
} else if ( useJsnext && pkg[ 'jsnext:main' ] ) {
pkg[ 'main' ] = pkg[ 'jsnext:main' ];
} else if ( ( useJsnext || useModule ) && !useMain ) {
let overriddenMain = false;
for ( let i = 0; i < mainFields.length; i++ ) {
const field = mainFields[i];
if ( typeof pkg[ field ] === 'string' ) {
pkg[ 'main' ] = pkg[ field ];
overriddenMain = true;
break;
}
}
if ( overriddenMain === false && mainFields.indexOf( 'main' ) === -1 ) {
disregardResult = true;
}
return pkg;
Expand All @@ -161,7 +189,7 @@ export default function nodeResolve ( options = {} ) {
Object.assign( resolveOptions, customResolveOptions )
)
.then(resolved => {
if ( resolved && options.browser && packageBrowserField ) {
if ( resolved && useBrowserOverrides && packageBrowserField ) {
if ( packageBrowserField.hasOwnProperty(resolved) ) {
if (!packageBrowserField[resolved]) {
browserMapCache[resolved] = packageBrowserField;
Expand Down
Loading

0 comments on commit 68f80df

Please sign in to comment.