Skip to content

Commit

Permalink
feat(node-resolve): add new option, modulePaths (#1104)
Browse files Browse the repository at this point in the history
* [node-resolve] Implement new modulePaths option

* Add unit tests distinguishing modulePaths from moduleDirectories

* Document new option

* Update packages/node-resolve/test/test.js

Co-authored-by: Tom Jenkinson <tjenkinson@users.noreply.github.com>

* Update packages/node-resolve/README.md

Co-authored-by: Tom Jenkinson <tjenkinson@users.noreply.github.com>

* fixup! Update packages/node-resolve/test/test.js

* Reject moduleDirectories containing a slash

* chore: arbitrary edit to kick github's actions ui

Co-authored-by: Andrew Hyndman <ahyndman@dropbox.com>
Co-authored-by: Tom Jenkinson <tjenkinson@users.noreply.github.com>
Co-authored-by: Andrew Powell <shellscape@users.noreply.github.com>
  • Loading branch information
4 people committed Sep 12, 2022
1 parent a43a6d6 commit 12d87a4
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 6 deletions.
11 changes: 9 additions & 2 deletions packages/node-resolve/README.md
Expand Up @@ -75,7 +75,14 @@ If `true`, instructs the plugin to use the browser module resolutions in `packag
Type: `Array[...String]`<br>
Default: `['node_modules']`

One or more directories in which to recursively look for modules.
A list of directory names in which to recursively look for modules.

### `modulePaths`

Type: `Array[...String]`<br>
Default: `[]`

A list of absolute paths to additional locations to search for modules. [This is analogous to setting the `NODE_PATH` environment variable for node](https://nodejs.org/api/modules.html#loading-from-the-global-folders).

### `dedupe`

Expand Down Expand Up @@ -214,7 +221,7 @@ export default ({
})
```

## Resolving require statements
## Resolving Require Statements

According to [NodeJS module resolution](https://nodejs.org/api/packages.html#packages_package_entry_points) `require` statements should resolve using the `require` condition in the package exports field, while es modules should use the `import` condition.

Expand Down
9 changes: 8 additions & 1 deletion packages/node-resolve/src/index.js
Expand Up @@ -44,7 +44,7 @@ export function nodeResolve(opts = {}) {
const { warnings } = handleDeprecatedOptions(opts);

const options = { ...defaults, ...opts };
const { extensions, jail, moduleDirectories, ignoreSideEffectsForRoot } = options;
const { extensions, jail, moduleDirectories, modulePaths, ignoreSideEffectsForRoot } = options;
const conditionsEsm = [...baseConditionsEsm, ...(options.exportConditions || [])];
const conditionsCjs = [...baseConditionsCjs, ...(options.exportConditions || [])];
const packageInfoCache = new Map();
Expand All @@ -57,6 +57,12 @@ export function nodeResolve(opts = {}) {
let { dedupe } = options;
let rollupOptions;

if (moduleDirectories.some((name) => name.includes('/'))) {
throw new Error(
'`moduleDirectories` option must only contain directory names. If you want to load modules from somewhere not supported by the default module resolution algorithm, see `modulePaths`.'
);
}

if (typeof dedupe !== 'function') {
dedupe = (importee) =>
options.dedupe.includes(importee) || options.dedupe.includes(getPackageName(importee));
Expand Down Expand Up @@ -167,6 +173,7 @@ export function nodeResolve(opts = {}) {
useBrowserOverrides,
baseDir,
moduleDirectories,
modulePaths,
rootDir,
ignoreSideEffectsForRoot
});
Expand Down
12 changes: 11 additions & 1 deletion packages/node-resolve/src/resolveImportSpecifiers.js
Expand Up @@ -43,6 +43,7 @@ async function resolveIdClassic({
useBrowserOverrides,
baseDir,
moduleDirectories,
modulePaths,
rootDir,
ignoreSideEffectsForRoot
}) {
Expand Down Expand Up @@ -77,6 +78,7 @@ async function resolveIdClassic({
extensions,
includeCoreModules: false,
moduleDirectory: moduleDirectories,
paths: modulePaths,
preserveSymlinks,
packageFilter: filter
};
Expand Down Expand Up @@ -111,6 +113,7 @@ async function resolveWithExportMap({
useBrowserOverrides,
baseDir,
moduleDirectories,
modulePaths,
rootDir,
ignoreSideEffectsForRoot
}) {
Expand All @@ -130,7 +133,8 @@ async function resolveWithExportMap({
preserveSymlinks,
useBrowserOverrides,
baseDir,
moduleDirectories
moduleDirectories,
modulePaths
});
}
});
Expand Down Expand Up @@ -180,6 +184,7 @@ async function resolveWithExportMap({
extensions,
includeCoreModules: false,
moduleDirectory: moduleDirectories,
paths: modulePaths,
preserveSymlinks,
packageFilter: filter
};
Expand Down Expand Up @@ -230,6 +235,7 @@ async function resolveWithClassic({
useBrowserOverrides,
baseDir,
moduleDirectories,
modulePaths,
rootDir,
ignoreSideEffectsForRoot
}) {
Expand All @@ -247,6 +253,7 @@ async function resolveWithClassic({
useBrowserOverrides,
baseDir,
moduleDirectories,
modulePaths,
rootDir,
ignoreSideEffectsForRoot
});
Expand Down Expand Up @@ -275,6 +282,7 @@ export default async function resolveImportSpecifiers({
useBrowserOverrides,
baseDir,
moduleDirectories,
modulePaths,
rootDir,
ignoreSideEffectsForRoot
}) {
Expand All @@ -290,6 +298,7 @@ export default async function resolveImportSpecifiers({
useBrowserOverrides,
baseDir,
moduleDirectories,
modulePaths,
rootDir,
ignoreSideEffectsForRoot
});
Expand All @@ -315,6 +324,7 @@ export default async function resolveImportSpecifiers({
useBrowserOverrides,
baseDir,
moduleDirectories,
modulePaths,
rootDir,
ignoreSideEffectsForRoot
});
Expand Down
@@ -0,0 +1,3 @@
import PACKAGE, {dependency} from 'package-with-dependency';

export { PACKAGE, dependency };

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

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

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

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

29 changes: 28 additions & 1 deletion packages/node-resolve/test/test.js
Expand Up @@ -8,7 +8,7 @@ import { rollup } from 'rollup';

import { nodeResolve } from '..';

import { getCode, getImports, testBundle } from '../../../util/test';
import { evaluateBundle, getCode, getImports, testBundle } from '../../../util/test';

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

Expand Down Expand Up @@ -273,6 +273,33 @@ test('allows custom moduleDirectories with legacy customResolveOptions.moduleDir
t.snapshot(warnings);
});

test('moduleDirectories option rejects paths that contain a slash', async (t) => {
t.throws(
() =>
nodeResolve({
moduleDirectories: ['some/path']
}),
{
message: /must only contain directory names/
}
);
});

test('allows custom modulePaths', async (t) => {
const bundle = await rollup({
input: 'custom-module-path/main.js',
onwarn: failOnWarn(t),
plugins: [
nodeResolve({
modulePaths: [join(process.cwd(), 'custom-module-path/node_modules')]
})
]
});

const { dependency } = await evaluateBundle(bundle);
t.is(dependency, 'DEPENDENCY');
});

test('ignores deep-import non-modules', async (t) => {
const warnings = [];
const bundle = await rollup({
Expand Down
9 changes: 8 additions & 1 deletion packages/node-resolve/types/index.d.ts
Expand Up @@ -31,11 +31,18 @@ export interface RollupNodeResolveOptions {
browser?: boolean;

/**
* One or more directories in which to recursively look for modules.
* A list of directory names in which to recursively look for modules.
* @default ['node_modules']
*/
moduleDirectories?: string[];

/**
* A list of absolute paths to additional locations to search for modules.
* This is analogous to setting the `NODE_PATH` environment variable for node.
* @default []
*/
modulePaths?: string[];

/**
* An `Array` of modules names, which instructs the plugin to force resolving for the
* specified modules to the root `node_modules`. Helps to prevent bundling the same
Expand Down

0 comments on commit 12d87a4

Please sign in to comment.