esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

Determining path to a dependency within resolve plugin

Open paralin opened this issue 1 year ago • 6 comments

How can I determine the path to the root directory of a npm package with esbuild based on an import? For example if I am resolving "import react" in a plugin, how can I determine that it's located at node_modules/react?

#3413 would have made this possible by resolving package.json and then getting the dirname from that. But since that isn't allowed due to the export rules in the nodejs specification, how can this be done?

paralin avatar Sep 29 '23 17:09 paralin

That's up to you really. It sounds like you have custom requirements so you might need something custom. For example, you could use a library such as https://github.com/browserify/resolve that I believe is supposed to give you lots of options for how packages are resolved as well as callbacks for various parts of the process.

evanw avatar Sep 29 '23 21:09 evanw

@evanw I'm confused because this seems like duplication of concerns. If I apply the PR #3413 and then resolve package.json, esbuild finds the root of the module just fine. So why do we need a separate js-based resolve when esbuild is capable of doing it with a pure-Go approach?

paralin avatar Sep 29 '23 21:09 paralin

You never really said why you're trying to do what you're asking for, so I'm not exactly sure what to recommend. If you need something custom that can tweak various steps of the package resolution algorithm then esbuild's default package resolution algorithm may not be what you need. That's why I was recommending something more customizable.

You could always use esbuild's package resolution algorithm to resolve the entry point for the package, but as you have seen package authors are allowed to customize path resolution for anything within their package so that may still not give you want you want (e.g. the package author may have disabled the entry point, although that wouldn't result in a particularly useful package).

evanw avatar Sep 29 '23 21:09 evanw

Okay, I'll provide more info. I'm trying to resolve the root directory of a package within node_modules because I'm working on a compiler tool that runs esbuild on third party dependencies to bundle them as external modules that are required through the "external" mechanism in esbuild.

At the moment I do everything in Go and was hoping to keep it that way. (Thanks to esbuild which is fantastic). However, I need the patch I showed in the PR to be able to locate the root directory of each node_modules package.

Since I'm already able to do this with esbuild within the OnResolve callback, I was hoping there would be some way to accomplish this properly with esbuild.

paralin avatar Sep 29 '23 23:09 paralin

FWIW a hack to use here that would likely work fine in the vast majority of cases without actually resolving the intermediate path to the package could be to resolve the entry point and then search for the last node_modules/[@optional-scope/]package-name segment in the path to get the path to the package.

evanw avatar Nov 19 '23 04:11 evanw

@evanw while this might work in most cases, (I think even it would work with npm link? But does someone resolve the symlink there before the path is evaluated?), the solution of asking esbuild nicely which package.json it used to resolve the import is a lot more reliable (it seems) in the long run. I still wonder if there's some way that this could be allowed in the API, since it's such a minor change (to allow resolving package.json) and while it's not part of the spec, perhaps some alternative path to asking for this information is possible.

paralin avatar Nov 19 '23 05:11 paralin