Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(node-resolve): Mark built-ins as external #627

Merged
merged 20 commits into from Nov 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 4 additions & 14 deletions packages/node-resolve/README.md
Expand Up @@ -112,7 +112,7 @@ Specifies the extensions of files that the plugin will operate on.
Type: `String`<br>
Default: `'/'`

Locks the module search within specified path (e.g. chroot). Modules defined outside this path will be marked as external.
Locks the module search within specified path (e.g. chroot). Modules defined outside this path will be ignored by this plugin.

### `mainFields`

Expand All @@ -129,7 +129,6 @@ DEPRECATED: use "resolveOnly" instead
### `preferBuiltins`

Type: `Boolean`<br>
Default: `true`

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.

Expand Down Expand Up @@ -183,20 +182,11 @@ export default {

## Resolving Built-Ins (like `fs`)

This plugin won't resolve any builtins (e.g. `fs`). If you need to resolve builtins you can install local modules and set `preferBuiltins` to `false`, or install a plugin like [rollup-plugin-node-polyfills](https://github.com/ionic-team/rollup-plugin-node-polyfills) which provides stubbed versions of these methods.
By default this plugin will prefer built-ins over local modules, marking them as external.

If you want to silence warnings about builtins, you can add the list of builtins to the `externals` option; like so:
See [`preferBuiltins`](#preferbuiltins).

```js
import resolve from '@rollup/plugin-node-resolve';
import builtins from 'builtin-modules'
export default ({
input: ...,
plugins: [resolve()],
external: builtins,
output: ...
})
```
Use a plugin like [rollup-plugin-node-polyfills](https://github.com/ionic-team/rollup-plugin-node-polyfills) to provide stubbed versions of built-ins, and set `preferBuiltins` to `false`.

## Resolving require statements

Expand Down
4 changes: 2 additions & 2 deletions packages/node-resolve/src/index.js
Expand Up @@ -259,14 +259,14 @@ export function nodeResolve(opts = {}) {

if (hasPackageEntry) {
if (builtins.has(resolved) && preferBuiltins && isPreferBuiltinsSet) {
return null;
return false;
} else if (importeeIsBuiltin && preferBuiltins) {
if (!isPreferBuiltinsSet) {
this.warn(
`preferring built-in module '${importee}' over local alternative at '${resolved}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning`
);
}
return null;
return false;
} else if (jail && resolved.indexOf(normalize(jail.trim(sep))) !== 0) {
tjenkinson marked this conversation as resolved.
Show resolved Hide resolved
return null;
}
Expand Down
26 changes: 9 additions & 17 deletions packages/node-resolve/src/resolveImportSpecifiers.js
Expand Up @@ -160,38 +160,30 @@ async function resolveId(importPath, options, exportConditions, warn) {

// Resolve module specifiers in order. Promise resolves to the first module that resolves
// successfully, or the error that resulted from the last attempted module resolution.
export function resolveImportSpecifiers(
export async function resolveImportSpecifiers(
importSpecifierList,
resolveOptions,
exportConditions,
warn
) {
let promise = Promise.resolve();

for (let i = 0; i < importSpecifierList.length; i++) {
// eslint-disable-next-line no-loop-func
promise = promise.then(async (value) => {
// if we've already resolved to something, just return it.
if (value) {
return value;
}

try {
// eslint-disable-next-line no-await-in-loop
let result = await resolveId(importSpecifierList[i], resolveOptions, exportConditions, warn);
if (!resolveOptions.preserveSymlinks) {
// eslint-disable-next-line no-await-in-loop
if (await exists(result)) {
// eslint-disable-next-line no-await-in-loop
result = await realpath(result);
}
}
return result;
});

// swallow MODULE_NOT_FOUND errors
promise = promise.catch((error) => {
} catch (error) {
// swallow MODULE_NOT_FOUND errors
if (error.code !== 'MODULE_NOT_FOUND') {
throw error;
}
});
}
}

return promise;
return null;
}
8 changes: 3 additions & 5 deletions packages/node-resolve/test/prefer-builtins.js
Expand Up @@ -9,7 +9,7 @@ const { nodeResolve } = require('..');

process.chdir(join(__dirname, 'fixtures'));

test('warns when importing builtins', async (t) => {
test('handles importing builtins', async (t) => {
const warnings = [];
const bundle = await rollup({
input: 'builtins.js',
Expand All @@ -24,8 +24,7 @@ test('warns when importing builtins', async (t) => {

const { module } = await testBundle(t, bundle);

t.is(warnings.length, 1);
t.snapshot(warnings);
t.is(warnings.length, 0);
// eslint-disable-next-line global-require
t.is(module.exports, require('path').sep);
});
Expand Down Expand Up @@ -66,8 +65,7 @@ test('true allows preferring a builtin to a local module of the same name', asyn

const imports = await getImports(bundle);

t.is(warnings.length, 1);
t.snapshot(warnings);
t.is(warnings.length, 0);
t.deepEqual(imports, ['events']);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/node-resolve/test/snapshots/dedupe-custom.js.md
Expand Up @@ -2,7 +2,7 @@

The actual snapshot is saved in `dedupe-custom.js.snap`.

Generated by [AVA](https://ava.li).
Generated by [AVA](https://avajs.dev).

## can deduplicate custom module directory

Expand Down
2 changes: 1 addition & 1 deletion packages/node-resolve/test/snapshots/dedupe.js.md
Expand Up @@ -2,7 +2,7 @@

The actual snapshot is saved in `dedupe.js.snap`.

Generated by [AVA](https://ava.li).
Generated by [AVA](https://avajs.dev).

## dedupes deep imports by package name if dedupe is set

Expand Down
Binary file modified packages/node-resolve/test/snapshots/dedupe.js.snap
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/node-resolve/test/snapshots/jail.js.md
Expand Up @@ -2,7 +2,7 @@

The actual snapshot is saved in `jail.js.snap`.

Generated by [AVA](https://ava.li).
Generated by [AVA](https://avajs.dev).

## mark module outside the jail as external

Expand Down
8 changes: 4 additions & 4 deletions packages/node-resolve/test/snapshots/only.js.md
Expand Up @@ -2,7 +2,7 @@

The actual snapshot is saved in `only.js.snap`.

Generated by [AVA](https://ava.li).
Generated by [AVA](https://avajs.dev).

## deprecated: regex

Expand Down Expand Up @@ -30,19 +30,19 @@ Generated by [AVA](https://ava.li).
},
]

## regex
## handles nested entry modules

> Snapshot 1

[]

## specify the only packages to resolve
## regex

> Snapshot 1

[]

## handles nested entry modules
## specify the only packages to resolve

> Snapshot 1

Expand Down
Binary file modified packages/node-resolve/test/snapshots/only.js.snap
Binary file not shown.
32 changes: 1 addition & 31 deletions packages/node-resolve/test/snapshots/prefer-builtins.js.md
Expand Up @@ -2,7 +2,7 @@

The actual snapshot is saved in `prefer-builtins.js.snap`.

Generated by [AVA](https://ava.li).
Generated by [AVA](https://avajs.dev).

## false allows resolving a local module with the same name as a builtin module

Expand All @@ -16,33 +16,3 @@ Generated by [AVA](https://ava.li).
toString: Function {},
},
]

## true allows preferring a builtin to a local module of the same name

> Snapshot 1

[
{
code: 'UNRESOLVED_IMPORT',
importer: 'prefer-builtin.js',
message: '\'events\' is imported by prefer-builtin.js, but could not be resolved – treating it as an external dependency',
source: 'events',
toString: Function {},
url: 'https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency',
},
]

## warns when importing builtins

> Snapshot 1

[
{
code: 'UNRESOLVED_IMPORT',
importer: 'builtins.js',
message: '\'path\' is imported by builtins.js, but could not be resolved – treating it as an external dependency',
source: 'path',
toString: Function {},
url: 'https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency',
},
]
Binary file modified packages/node-resolve/test/snapshots/prefer-builtins.js.snap
Binary file not shown.
8 changes: 1 addition & 7 deletions packages/node-resolve/test/snapshots/root-dir.js.md
Expand Up @@ -2,13 +2,7 @@

The actual snapshot is saved in `root-dir.js.snap`.

Generated by [AVA](https://ava.li).

## deduplicated from the given root directory

> Snapshot 1

'Package A React: react imported from root | package B react: react imported from root'
Generated by [AVA](https://avajs.dev).

## deduplicates modules from the given root directory

Expand Down
Binary file modified packages/node-resolve/test/snapshots/root-dir.js.snap
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/node-resolve/test/snapshots/test.js.md
Expand Up @@ -2,7 +2,7 @@

The actual snapshot is saved in `test.js.snap`.

Generated by [AVA](https://ava.li).
Generated by [AVA](https://avajs.dev).

## handles package side-effects

Expand Down
Binary file modified packages/node-resolve/test/snapshots/test.js.snap
Binary file not shown.