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): add new option, modulePaths #1104

Merged
merged 8 commits into from Sep 12, 2022
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
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