-
-
Notifications
You must be signed in to change notification settings - Fork 431
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
Implements a custom resolveModuleName option #862
Implements a custom resolveModuleName option #862
Conversation
src/interfaces.ts
Outdated
export type CustomResolveModuleName = ( | ||
moduleName: string, | ||
containingFile: string, | ||
options: typescript.CompilerOptions, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be called compilerOptions
also please?
src/servicesHost.ts
Outdated
compilerOptions, | ||
moduleResolutionHost | ||
); | ||
const tsResolver = (moduleName: string, containingFile: string, compilerOptions: typescript.CompilerOptions, moduleResolutionHost: typescript.ModuleResolutionHost) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given tsResolver
is a pure function could we break this out in to a separate function please? That saves creating a new function each time this runs.
Thanks for this! Could you address the comments and fix the linting errors that are showing up in CI please? |
Regarding testing, it would be good to implement an execution test to cover this. You can find out more about these here: https://github.com/TypeStrong/ts-loader/blob/master/test/execution-tests/README.md A good example to clone as a basis for your test might be this one: or |
src/servicesHost.ts
Outdated
const tsResolution = customResolveModuleName | ||
? customResolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost, tsResolver) | ||
: tsResolver(moduleName, containingFile, compilerOptions, moduleResolutionHost); | ||
? customResolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost, applyTsResolver.bind(null, compiler)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hadn't expected the .bind(null, compiler)
would be necessary... I'm guessing it is? What happens without it? Presumably some kind of this
issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we simply need the compiler
variable to be able to call compiler.resolveModuleName
(and compiler
is obtained from instance
, which isn't a global)
{ | ||
"compilerOptions": { | ||
"noEmitOnError": true, | ||
"resolveJsonModule": true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we remove the "resolveJsonModule": true
please? It doesn't do any harm but it might lead someone who was reading the test to believe that it was necessary for resolveModuleName
to work. (Not least because of the similarity in naming 😄 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure 👍
import * as app from '../src/app'; | ||
|
||
// We don't actually care about the result of the following operations; | ||
// what we care about is typescript resolving json as modules |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you amend the comment to reflect what the intention of the test is please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left the comment because it's actually the same intent - we don't care about what is being built, just about TS being able to make the resolution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see a "json" is in the comment - will change it 👍
Good work on the changes @arcanis! I've a couple more comments that I've added just now. Well done on the execution test. Looks good! Question though: it looks like it's only resolving types from Does that sound sensible? Or have I misunderstood your intent? |
@johnnyreilly I wasn't entirely sure if the generated code had to be tested as well, since I wasn't sure whether ts-loader was entirely relying on TypeScript for the resolution or not (versus only using it for the type resolution, leaving the regular Webpack resolver setup the links between the packages). What do you think? |
Yes please!
It's a good question. https://github.com/TypeStrong/ts-loader/blob/master/src/resolver.ts Funnily enough, it's on my radar to try out using TypeScript for resolve module names resolution too, but as yet I haven't. See: #757 (comment) |
Let me know if that matches what you had in mind :) |
src/servicesHost.ts
Outdated
containingFile, | ||
compilerOptions, | ||
moduleResolutionHost, | ||
applyTsResolver.bind(null, compiler) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing a .bind
my perf spider sense is tingling!
https://stackoverflow.com/questions/42117911/lambda-functions-vs-bind-memory-and-performance
I wonder if we could switch this to a lamba instead? It'll be slightly more verbose but hopefully should perform better...
@@ -0,0 +1,13 @@ | |||
import * as app from '../src/app'; | |||
|
|||
// We don't actually care about the result of the following operations; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not true actually; we do care about the result of the following operations! Can we amend the comment to make test intent clearer please? We care both about type resolution and that the code executes...
Thanks chap! I've put a few comments in and I've also fixed the failing comparison test on your branch. I think the execution test is better but it's still not quite what I had in mind; let me explain: As I understand it That being the case you'd likely not consume them with raw TypeScript files in; you'd either:
Or
If my understanding is correct then ideally our tests should be covering those scenarios rather than exporting raw .ts. It's possible my understanding of this feature is not quite right; feel free to set me straight! 😄 |
I think the first scenario you mention isn't relevant to I've updated |
Cool - thanks for that! I've just fixed up the linting errors; hopefully we should now see a clean CI 😄 Question: in the test you only make use of the
That being the case, does it make sense for the All things being equal, I suspect we're pretty much there! |
Ping @arcanis 😉 |
Sorry, was flying yesterday 🙂 So it don't use those values yet (and I'm not too familiar with TS to know what they're used for, tbh), but since the TS resolveModuleName hook requires all four of them I figured it'd make sense to also accept them, since they're easily available to us while the hook doesn't have any way to know them otherwise l. One particular advantage is that it will make it easier for different projects/loaders to use the same custom resolveModuleName implementation (which would be a bit more difficult if they were each expecting a different set of parameters). |
That sounds reasonable! Do you have anymore work to do on this or is this ready to merge from your perspective? |
Nope, I think it's ready on my side! |
Nice! Thanks for your work! Would you be able to update the That'll help me as I look to merge / publish this. |
d351782
to
bee1c37
Compare
Here you go! Minor, right? 👍 |
Thanks! Published with v5.3.0 |
Solves #861 - This PR adds a new
resolveModuleName
option that can be used to help TypeScript figure out the location of the files on the disk. It mimics the TypeScript API.I published a first implementation as part of ts-pnp, and it can be tested using the pnp-webpack-plugin which provides an integration.
I'm not too sure how and where I should test this - any advice?