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

Fully custom module resolution logic #2837

Closed
Phoenixmatrix opened this issue Feb 8, 2017 · 7 comments
Closed

Fully custom module resolution logic #2837

Phoenixmatrix opened this issue Feb 8, 2017 · 7 comments

Comments

@Phoenixmatrix
Copy link

Do you want to request a feature or report a bug?

Feature request

What is the current behavior?

If I understand well, right now the only control to change how modules are resolved is via the moduleNameMapper, which has some limits on customization when compared to the environment the code might run in normally (eg: webpack with custom resolvers, plugins, etc)

What is the expected behavior?

I'm wondering if it would be possible to implement a fully custom module resolver of some sort. Something that, when running eg require('foo/bar'), would send 'foo/bar' to a function which could do anything and return at a minimum a new path at which to resolve the module, or even better, a loaded module. This could be used to support legacy AMD code as a first class citizen, but in my particular case, we have a completely custom module resolution system (for a lot of reasons and won't bore you with the details here) that is completely different from node's. We have stuff implemented in webpack to make it work there, and it would be nice to be able to implement something similar in Jest.

I'd be more than happy to implement this myself, and I probably can poke at the codebase and figure it out on my own, but if I was to do it, I'd be interested to doing in a way that it could have a shot in hell of being merged back upstream so I don't have to maintain a fork.

Any opinions/questions/thoughts/comments?

Thanks!

@cpojer
Copy link
Member

cpojer commented Feb 9, 2017

Yes this is certainly possible but we need to figure out at what level this makes the most sense. I've been thinking about this for a long time and would love to see this implemented.

Should it simply be a "resolve" config option that is a simple function or shall we allow to subclass jest-resolve or jest-resolve-dependencies and overwrite all behavior in Jest?

The second thought I had, I actually wanted to take the resolve npm package and rewrite the sync part for performance inside of jest-resolve. Currently it isn't really optimized and we have more info about the file system that we could use to speed up Jest itself. This is a really good follow-up fun project for anybody who wants to contribute to Jest :)

@Phoenixmatrix
Copy link
Author

Phoenixmatrix commented Feb 9, 2017

So I haven't looked much at the existing code at all yet, but my guts feeling is that it shouldn't make any assumptions about the implementation detail. You'd point your config to a module, the module has the proper interface. Done. If you subclass jest-resolve or compose it or whatever, that would work since you're keeping the interface, and if you decide to go from scratch, that works too (while I don't have that requirement, it would make it easier to decouple from node and, eg, run in the browser someday)

That way an implementation could handle caching behavior however it wishes and whatsnot.

It's not as easy as allowing just a little function that could return something, and if it returns false falls back to the original behavior, but ^ that could easily be implemented then.

What I'm unable to figure out (though I only looked through the code for 2-3 minutes) is what you alluded to: is it at the jest-resolve level or jest-resolve-dependencies? We'd want whatever resolution mechanism to implement to affect -everything- (else it defeats the purpose), and ideally do that by implementing a single interface,

@cpojer
Copy link
Member

cpojer commented Feb 9, 2017

Yes so the question is what that interface would look like? jest-resolve-dependencies is used for features like jest -o but it uses jest-resolve to do the actual resolution. I think if the interface to swap out is jest-resolve, then this would work well. The only thing I'm not sure about is if that is too much, like should we start out by supporting an interface smaller than what jest-resolve currently provides?

@Phoenixmatrix
Copy link
Author

I think what I'm going to do with that in mind is start by doing something around swapping jest-resolve for an arbitrary module, and then we can look at the diff and iterate from there. If you decide it was the wrong way to go and we go back to the drawing board, it's no skin off my back.

@cpojer
Copy link
Member

cpojer commented Feb 9, 2017

Let's try it, as long as it can be composed this may work :)

@dlmr
Copy link
Contributor

dlmr commented Feb 27, 2017

I have created a PR (#2998) that I think solves this issue in a generic way that should work in most situations. Would be awesome if you could take a look @Phoenixmatrix and see if it work for your use case as well.

@cpojer cpojer closed this as completed Mar 3, 2017
@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants