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

Yarn PnP support #154

Closed
rtsao opened this issue May 26, 2020 · 7 comments
Closed

Yarn PnP support #154

rtsao opened this issue May 26, 2020 · 7 comments

Comments

@rtsao
Copy link
Contributor

rtsao commented May 26, 2020

Have you considered support for Yarn PnP? PnP is a faster alternative to node_modules used by Yarn 2. Webpack, Parcel, Rollup, and TypeScript currently support PnP.

Because esbuild is implemented in Go rather than JS, PnP support will probably be a larger undertaking, but I figured I would create an issue to gauge maintainer and community interest.

@evanw
Copy link
Owner

evanw commented May 26, 2020

No I haven't. As you pointed out, it's not a good fit for esbuild because the module resolution involves executing arbitrary JavaScript code instead of following a well-defined algorithm.

I'm not sure if it's a valid alternative, but you could consider pnpm instead. That uses symlinks as a faster alternative to node_modules and esbuild has been updated to support it: #67.

It's possible that esbuild might have some form of "resolve plugin" API in the future which would make this possible. Either that or it could potentially expose an API that would let you build your own bundler that supports PnP and uses esbuild as a backend. But such an API won't be coming soon because esbuild isn't that mature yet.

@rtsao
Copy link
Contributor Author

rtsao commented May 26, 2020

Theoretically speaking, if someone was willing to implement PnP resolution natively in Go (perhaps as a separate library), would you consider accepting PnP resolution into esbuild core (perhaps as a CLI flag)?

I'm wondering what approach might incur the least amount of maintenance burden. It might be worth just implementing PnP in Go rather than dealing with JS FFI or having to maintain some plugin abstraction. I haven't had a chance to dive into the codebase yet, but do you think the current resolution code could support an alternate resolution algorithm without too much extra complexity?

Obviously PnP is relatively new to the ecosystem, but I could see PnP support be a blocker for a growing number users. That being said, it is totally understandable if you'd be unwilling to maintain PnP support.

@evanw
Copy link
Owner

evanw commented May 27, 2020

It doesn't seem appropriate to have this be a part of esbuild, so I don't think I would accept a PR for this. After reading yarnpkg/yarn#6388 it looks like they deliberately made the resolution strategy depend on executing JavaScript because they want to maintain the ability to evolve the implementation. So it seems like the intended design is for the loader to call into their library.

A JavaScript plugin would be the most appropriate way to do this. Unfortunately esbuild isn't ready for JavaScript plugins. I plan to start experimenting with them at some point, and if/when I do I will keep a "resolve plugin" API in mind for this use case.

@rtsao rtsao closed this as completed May 27, 2020
@arcanis
Copy link

arcanis commented May 27, 2020

Hey 👋 A few tidbits of context I shared on Discord:

the module resolution involves executing arbitrary JavaScript code instead of following a well-defined algorithm

It is well-defined; the problems are 1/ the data structures, which we don't generate in a stable format (but you can easily treat the generated PnP API as an intermediary to a stable format of your choice, for example a stable JSON file or import maps), 2/ the algorithm itself, which you need to reimplement.

Since there are very few projects that need to implement the PnP resolution in other languages, we didn't see the need to provide the runtime in other languages (it would come with maintainance work that we don't really need).

That being said, note that the .pnp.js file is also a valid standalone JS script ... if you run it without arguments, it'll spawn in daemon mode and you'll be able to interact with it through stdin/stdout there's a very basic protocol that allows calling the resolution and reading back the results that's how we implemented Flow PnP support, back in the day. Caveats: you still need to execute JS, in the end / resolution is a bit slower / you still need to add the zip layer support to the native tool (this is what was the final blocker with Flow).

@evanw
Copy link
Owner

evanw commented May 27, 2020

Thanks for stopping by to provide more information.

it'll spawn in daemon mode and you'll be able to interact with it through stdin/stdout

This sounds like what I had in mind for JavaScript plugins (see #111). So that confirms to me that this would probably be best as a JavaScript plugin, since it makes sense to build a mechanism like that into esbuild once, not twice. The plugin could just call out to Yarn's API.

@dmattia
Copy link

dmattia commented Mar 5, 2021

Just some resolution to this closed issue in case anyone else stops by, yarn now officially supports a esbuild plugin for pnp that they use internally to build yarn itself: https://github.com/yarnpkg/berry/tree/master/packages/esbuild-plugin-pnp

@evanw
Copy link
Owner

evanw commented Aug 10, 2022

FYI: Native support for PnP has been added to esbuild: https://github.com/evanw/esbuild/releases/tag/v0.15.0 (it became possible to implement this now that the PnP data format has been documented: https://yarnpkg.com/advanced/pnp-spec/).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants