Within the boundary of a npm package (defined as being in a subpath of a folder containing a package.json), barring exotic circumstances, the following types of module resolution are invariant to the requesting file's relativePath from the descriptionFileRoot:
- Absolute paths. These may only be altered by
alias or other plugins, and are generally unaffected by the requesting package at all.
- Bare specifiers, e.g.
react, @nodelib/fs.scandir. These are only impacted by the presence of node_modules folders, which no normal package manager will create in subfolders of a package without there being a nested package.json. As such, resolution can ignore the relativePath component of the requesting file.
- Imports that map through the package.json
imports field via ala #some/request. These do not provide any means for the relativePath component of the requesting file to impact resolution.
- A relative import
../foo from a/bar is exactly the same as a relative import ./foo from a.
Based on the above, we can optimize the caching layer for resolution requests as follows:
- Assume that a cache key contains
internal, path, request, query, fragment (there may be other fields that it still splits on, but these are generally the majority of the differentiation)
- If the request is a relative path, update
request = joinRelativePreservingLeadingDot(relativePath, request)
- Set
path = descriptionFileRoot in the cache key in all cases
Testing in a large local project, this mapping reduced the number of unique requests seen by the resolver by about 33%, which both reduces the size of the cache and improves the cache hit rate.
This optimization is particularly relevant for packages that contain a lot of subfolders.
One can further optimize the cache hit rate by having a cache layer and performing request normalization any time the descriptionFileRoot property of the request object changes, for example upon resolving the request to a target package.
Within the boundary of a npm package (defined as being in a subpath of a folder containing a
package.json), barring exotic circumstances, the following types of module resolution are invariant to the requesting file'srelativePathfrom thedescriptionFileRoot:aliasor other plugins, and are generally unaffected by the requesting package at all.react,@nodelib/fs.scandir. These are only impacted by the presence ofnode_modulesfolders, which no normal package manager will create in subfolders of a package without there being a nestedpackage.json. As such, resolution can ignore therelativePathcomponent of the requesting file.importsfield via ala#some/request. These do not provide any means for therelativePathcomponent of the requesting file to impact resolution.../foofroma/baris exactly the same as a relative import./foofroma.Based on the above, we can optimize the caching layer for resolution requests as follows:
internal,path,request,query,fragment(there may be other fields that it still splits on, but these are generally the majority of the differentiation)request = joinRelativePreservingLeadingDot(relativePath, request)path = descriptionFileRootin the cache key in all casesTesting in a large local project, this mapping reduced the number of unique requests seen by the resolver by about 33%, which both reduces the size of the cache and improves the cache hit rate.
This optimization is particularly relevant for packages that contain a lot of subfolders.
One can further optimize the cache hit rate by having a cache layer and performing request normalization any time the
descriptionFileRootproperty of the request object changes, for example upon resolving the request to a target package.