Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 032055b

Browse filesBrowse files
authored
feat(node-resolve): allow preferBuiltins to be a function (#1694)
* feat: allow `options.preferBuiltins` to be function * docs: update readme * feat: add types in dts * tests: add testcase about passing function to preferBuiltins
1 parent 0af45c2 commit 032055b
Copy full SHA for 032055b

File tree

5 files changed

+57
-14
lines changed
Filter options

5 files changed

+57
-14
lines changed

‎packages/node-resolve/README.md

Copy file name to clipboardExpand all lines: packages/node-resolve/README.md
+9-1Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,19 @@ Specifies the properties to scan within a `package.json`, used to determine the
133133

134134
### `preferBuiltins`
135135

136-
Type: `Boolean`<br>
136+
Type: `Boolean | (module: string) => boolean`<br>
137137
Default: `true` (with warnings if a builtin module is used over a local version. Set to `true` to disable warning.)
138138

139139
If `true`, the plugin will prefer built-in modules (e.g. `fs`, `path`). If `false`, the plugin will look for locally installed modules of the same name.
140140

141+
Alternatively, you may pass in a function that returns a boolean to confirm whether the plugin should prefer built-in modules. e.g.
142+
143+
```js
144+
preferBuiltins: (module) => module !== 'punycode';
145+
```
146+
147+
will not treat `punycode` as a built-in module
148+
141149
### `modulesOnly`
142150

143151
Type: `Boolean`<br>

‎packages/node-resolve/src/index.js

Copy file name to clipboardExpand all lines: packages/node-resolve/src/index.js
+11-6Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export function nodeResolve(opts = {}) {
5858
const idToPackageInfo = new Map();
5959
const mainFields = getMainFields(options);
6060
const useBrowserOverrides = mainFields.indexOf('browser') !== -1;
61-
const isPreferBuiltinsSet = options.preferBuiltins === true || options.preferBuiltins === false;
61+
const isPreferBuiltinsSet = Object.prototype.hasOwnProperty.call(options, 'preferBuiltins');
6262
const preferBuiltins = isPreferBuiltinsSet ? options.preferBuiltins : true;
6363
const rootDir = resolve(options.rootDir || process.cwd());
6464
let { dedupe } = options;
@@ -194,8 +194,10 @@ export function nodeResolve(opts = {}) {
194194
});
195195

196196
const importeeIsBuiltin = builtinModules.includes(importee.replace(nodeImportPrefix, ''));
197+
const preferImporteeIsBuiltin =
198+
typeof preferBuiltins === 'function' ? preferBuiltins(importee) : preferBuiltins;
197199
const resolved =
198-
importeeIsBuiltin && preferBuiltins
200+
importeeIsBuiltin && preferImporteeIsBuiltin
199201
? {
200202
packageInfo: undefined,
201203
hasModuleSideEffects: () => null,
@@ -230,11 +232,14 @@ export function nodeResolve(opts = {}) {
230232
idToPackageInfo.set(location, packageInfo);
231233

232234
if (hasPackageEntry) {
233-
if (importeeIsBuiltin && preferBuiltins) {
235+
if (importeeIsBuiltin && preferImporteeIsBuiltin) {
234236
if (!isPreferBuiltinsSet && resolvedWithoutBuiltins && resolved !== importee) {
235-
context.warn(
236-
`preferring built-in module '${importee}' over local alternative at '${resolvedWithoutBuiltins.location}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning`
237-
);
237+
context.warn({
238+
message:
239+
`preferring built-in module '${importee}' over local alternative at '${resolvedWithoutBuiltins.location}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning.` +
240+
`or passing a function to 'preferBuiltins' to provide more fine-grained control over which built-in modules to prefer.`,
241+
pluginCode: 'PREFER_BUILTINS'
242+
});
238243
}
239244
return false;
240245
} else if (jail && location.indexOf(normalize(jail.trim(sep))) !== 0) {
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { sep } from 'path';
2+
import events from 'events';
3+
4+
export default { sep, events };

‎packages/node-resolve/test/prefer-builtins.js

Copy file name to clipboardExpand all lines: packages/node-resolve/test/prefer-builtins.js
+30-6Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,12 @@ test('handles importing builtins', async (t) => {
3030
});
3131

3232
test('warning when preferring a builtin module, no explicit configuration', async (t) => {
33-
let warning = null;
33+
let warning = '';
3434
await rollup({
3535
input: 'prefer-builtin.js',
36-
onwarn({ message }) {
37-
// eslint-disable-next-line no-bitwise
38-
if (~message.indexOf('preferring')) {
39-
warning = message;
36+
onwarn({ message, pluginCode }) {
37+
if (pluginCode === 'PREFER_BUILTINS') {
38+
warning += message;
4039
}
4140
},
4241
plugins: [nodeResolve()]
@@ -47,7 +46,8 @@ test('warning when preferring a builtin module, no explicit configuration', asyn
4746
warning,
4847
`preferring built-in module 'events' over local alternative ` +
4948
`at '${localPath}', pass 'preferBuiltins: false' to disable this behavior ` +
50-
`or 'preferBuiltins: true' to disable this warning`
49+
`or 'preferBuiltins: true' to disable this warning.` +
50+
`or passing a function to 'preferBuiltins' to provide more fine-grained control over which built-in modules to prefer.`
5151
);
5252
});
5353

@@ -134,3 +134,27 @@ test('detects builtins imported with node: protocol', async (t) => {
134134

135135
t.is(warnings.length, 0);
136136
});
137+
138+
test('accpet passing a function to determine which builtins to prefer', async (t) => {
139+
const warnings = [];
140+
const bundle = await rollup({
141+
input: 'prefer-builtin-local-and-builtin.js',
142+
onwarn({ message }) {
143+
warnings.push(message);
144+
},
145+
plugins: [
146+
nodeResolve({
147+
preferBuiltins: (id) => id !== 'events'
148+
})
149+
]
150+
});
151+
152+
const {
153+
module: { exports }
154+
} = await testBundle(t, bundle);
155+
156+
t.is(warnings.length, 0);
157+
t.is(exports.sep, require('node:path').sep);
158+
t.not(exports.events, require('node:events'));
159+
t.is(exports.events, 'not the built-in events module');
160+
});

‎packages/node-resolve/types/index.d.ts

Copy file name to clipboardExpand all lines: packages/node-resolve/types/index.d.ts
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,11 @@ export interface RollupNodeResolveOptions {
7979
/**
8080
* If `true`, the plugin will prefer built-in modules (e.g. `fs`, `path`). If `false`,
8181
* the plugin will look for locally installed modules of the same name.
82+
*
83+
* If a function is provided, it will be called to determine whether to prefer built-ins.
8284
* @default true
8385
*/
84-
preferBuiltins?: boolean;
86+
preferBuiltins?: boolean | ((module: string) => boolean);
8587

8688
/**
8789
* An `Array` which instructs the plugin to limit module resolution to those whose

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.