Description
tl;dr I'd like to propose an additional API be exposed to Node.js JavaScript that allows developers to perform require.resolve()
, but with an custom list of lookup paths.
Background
In ESLint, we allow people to extend their configuration files with Node.js packages, so you can do something like this:
extends: airbnb
And then ESLint require
s eslint-config-airbnb
. That worked fine until people started creating shareable configs, published on npm, that wanted to inherit from other shareable configs (also published on npm). In that case, they'd want the require
lookup to happen from their config file and not from the ESLint file doing the require
.
Our Solution
What we ended up doing to get this to work: https://github.com/eslint/eslint/blob/master/lib/util/module-resolver.js
In short:
- Create the normal array of lookup paths by combining
Module.globalPaths
andmodule.paths
- Prepend another path to the front of that array
- Use
Module._findPath()
to do the lookup, passing the lookup paths array
The obvious ugliness here is that we're not just relying on Module
, but we're relying on Module._findPath()
, which seems to indicate that this method should not be used (assuming the underscore is intended to mean "private".
What I'd Like
Some way to get the functionality of Module._findPath()
that is an official Node.js API that we can rely on without fear of it changing or being removed. Some possible options (definitely not exhaustive):
- Allow a second argument to
require.resolve()
that allows you to pass an array of lookup paths. - Bless
Module._findPath()
by creating something likeModule.resolveFromPaths()
that callsModule._findPath()
under the covers
Of course, these are just a few ideas I had in my head. Anything that accomplishes the same functionality would be awesome.
Prior Art
It seems like there's a larger need for this capability based on modules available on npm:
- resolve - effectively does the same thing by trying to recreate the Node.js lookup process. We tried using this, but there are enough differences with the real Node.js implementation that we abandoned it. It also hardcodes some information that should be dynamic (like core module names). 7 million downloads in the past month.
- resolve-module - a simpler and less popular version of the same thing.
- custom-resolve - a customized version of
resolve
. - resolve-cwd -
require.resolve
using CWD as the root. 50,000 downloads in the past month. - resolve-from -
require.resolve
from any arbitrary path. 1.5 million downloads in the past month.