-
-
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
Support project references #817
Support project references #817
Conversation
This is PR "1" of the potential 2 I guess? Great work so far! 👍 You've just reminded me that I need to update the comparison test pack for TS 3.0. I'll try and do that this weekend so you don't have to. I'll message here when it's done. |
I've upgraded the comparison test pack to 3.0 - feel free to merge that on to your pr |
Rebased against master with the updated tests 👍 Latest commit will fail; I'm going ahead and assuming we'll have |
src/index.ts
Outdated
|
||
if (!instance.compiler.sys.fileExists(mapFileName)) { | ||
loader.emitWarning( |
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.
It might be obnoxious to do this for every file. Maybe I can memoize by referencedProject.sourceFile.fileName
? Or would it make more sense to validate each project reference while first setting up the program/languageService/watch?
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.
That seems reasonable; presumably that's not something that changes often at all so should be a completely reasonable choice
@johnnyreilly can the comparison test’s "patch" feature be used to patch the test's I'm thinking about the scenarios that need to be tested, and they include all three modes of creating a TS program— It's also definitely going to be worth testing the error cases, as an unbuilt project reference would compile perfectly fine if project references weren’t working, if that makes sense (TypeScript would just compile the source files per usual, instead of saying “hey this is part of a project reference that’s not built”). Are comparison tests useful for asserting failed builds at all? Edit: I see the Webpack output is captured in a text file, so that looks pretty good for testing the error cases 👍 |
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.
Did a first pass at a comparison test. Not sure why there wasn't a .transpiled
version generated like some of the others have though?
To generate outputs for older TS versions, do I need to manually install each older version and run again?
"composite": true | ||
}, | ||
"files": [ | ||
"./index.ts" |
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.
For some reason, without files
or include
, program.getProjectReferences()[0].commandLine.fileNames
was empty. I thought it should have resolved to all *.ts
files by default?
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.
To generate outputs for older TS versions, do I need to manually install each older version and run again?
No - we only run comparison tests for the latest TypeScript version. So 3 alone is fine
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.
For some reason, without files or include, program.getProjectReferences()[0].commandLine.fileNames was empty. I thought it should have resolved to all *.ts files by default?
Without project references in the mix then that should be the case. Is it different when rolling with project references perhaps?
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.
Regards the lack of transpile; that's surprising but I wouldn't worry right now. This is the code that generates it BTW: https://github.com/TypeStrong/ts-loader/blob/master/test/comparison-tests/create-and-execute-test.js
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.
When I was testing ad-hoc, the reference.commandLine.fileNames
was working correctly, but I think I was using typescript@next... I'll have to investigate more.
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.
Ah, I was mistaken:
All implementation files must be matched by an include pattern or listed in the files array. If this constraint is violated, tsc will inform you which files weren’t specified
https://www.typescriptlang.org/docs/handbook/project-references.html#composite
It seems it's working as intended, but via our programmatic route we don't get that warning. Maybe need to add our own.
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 the comparison test’s "patch" feature be used to patch the test's webpack.config.js itself?
No I'm afraid not; the tests rely upon an unchanged webpack config between patches. Sorry
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.
It seems it's working as intended, but via our programmatic route we don't get that warning. Maybe need to add our own.
I'm not sure if this can be done reliably and efficiently... without actually doing a build of the dependent projects, it's hard to tell if a given file was intended to be included by one of them, or was just intended to be processed by the parent project (i.e. in our case, run through the loader). Implementing a warning from ts-loader side while consuming project references might be out of scope—hopefully it's something users will notice while actually running tsc
on those projects, since pre-building the referenced projects is currently required, and tsc
will emit the error if files
or include
don't cover all the files.
@johnnyreilly status update: Implementation
Tests
|
Sorry for the delay in responding @andrewbranch - I'm away and just have my phone and poor connectivity. In fact I'm typing this surrounded by 🐑 whilst lost rambling!
I'm not sure it is; my guess is that people will only use projectReferences with non-transpile mode. Either way this is fine for now in my view.
Thanks but no. What I actually mean to do at some point is tweak the comparison test pack so it runs in 3 modes: standard, transpileOnly and watchApi. So in the longer term separate tests for the watchApi shouldn't exist. It's just another part of the test matrix if you will.
They're not passing 😂 Jokes aside, I wouldn't worry about the tests for now. First get to an implementation that you're content with, let's review that together and then we can work together on the test that cover this new functionality until they are fully passing / covering the scenarios we care about. Thanks again for all the work you're doing; I really appreciate it. Much I should be back online in a week or so. Assuming I find the way out of this field 😉 |
Thanks! Hope you are enjoying your vacation. The build is failing because I wrote a line that assumes microsoft/TypeScript#26421 will be merged. I think maybe we just need to press on without that for now. I'll give it a few more days but have something mergeable by the time you're back. |
src/utils.ts
Outdated
program && | ||
program | ||
.getProjectReferences()! | ||
.find(ref => ref!.commandLine.fileNames.indexOf(filePath) > -1) |
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.
do you handle missing referenced projects somewhere else or how can you be sure ref
is always defined?
ref
will be undefined
if a referenced project cannot be resolved, i.e. missing folder or missing tsconfig.json.
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.
It will be a holey array? I didn't realize that; it feels a bit unintuitive, but I guess the types agree. Let me do something here. Thanks for the feedback!
src/index.ts
Outdated
const { outputText, sourceMapText } = options.transpileOnly | ||
? getTranspilationEmit(filePath, contents, instance, loader) | ||
: getEmit(rawFilePath, filePath, instance, loader); | ||
const jsFileName = instance.compiler.getOutputJavaScriptFileName( |
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 that the whole tsbuild API is now internal, this uses an internal function? I couldn't find a custom implementation if it in this PR
@andrewbranch that change was published in typescript@next a few days ago |
Thanks @ajafff! All yours @andrewbranch! |
This doesn't seem to be the case insofar as what At any rate, ddc5cc7 runs
By all means!
🙏 |
I'm already using |
Ok, cool, thanks @ajafff. Confirmed that Working on the README now. |
@johnnyreilly as I'm writing this README, I'm thinking that it honestly sounds kind of silly at this point without yet having support for building upstream projects. I think probably very few people will want to try out the feature before there's a solid solution for having everything built for you. A somewhat interesting effect of ts-loader not yet supporting project references in If we ship this now, enabled by default, without support for rebuilding upstream projects, we'll technically break those people, because all of a sudden, project references will start half-working instead of being ignored. Folks may not realize that ts-loader stopped building their files. I'm thinking we need to put all this work behind a loader option. What do you think? |
Oooh - good catch! Yes that makes sense. If you could include that information in the README that would be good. What do you think would be a good name for the I'll probably write a blog post when this ships to publicise that this feature is available and that it's opt-in. I'll plan to use some of your README tweaks for part of that (giving credit where it's due of course ❤️ 😄 ) Working on ignoring the test on Windows now. |
Awesome. After so much work, it's slightly disappointing that it’s not super usable yet, but I really think the hardest part is done. (🤞🙈) I may not be able to pick back up right away, but if nobody else jumps on it, I’ll want to see it through and figure out building upstream projects. That said, I’d be thrilled if someone else does want to champion that part, but my own sense of sunk cost won’t let me leave it half-done. 😄 |
Completely agree.
😄 |
I'd forgotten just how fiddly / flaky the comparison test pack can be. Decided to use the opportunity to introduce a whole suite of fancy logic around ignoring tests. Managed to break the existing test pack in the process 🤦 Totally unnecessary. Will replace https://github.com/TypeStrong/ts-loader/blob/master/test/comparison-tests/create-and-execute-test.js#L55 with something as simple as:
Not tested this yet; wrote it on a Google Pixel on a train whilst reading the node docs on a spotty connection. 😄 Heading into work now; will try and take another look tonight / this weekend |
Cool - that worked. I'll see if I can make a start on execution tests this weekend. |
Hey @andrewbranch , It's time to 🚢! I'm planning to push out this as version 5.2.0. I'll put a note in the README about the I'm going to write a blogpost to let people know about this new feature. I'm planning to plagiarise your excellent update to the README pretty heavily. I hope that's okay! Thanks again for all your hard work. It's greatly appreciated! Much ❤️ |
Woop! 🙌🏼 Thanks for all the support throughout the process. This has been fun! Plagiarize away! 😄 |
Closes #815
TODO:
transpileOnly
experimentalWatchApi
for each of the three modes above,one test for a successful build and one that fails because the dependent project isn’t built)