-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
[Feature]: Allow using tsx instead of ts-node for loading TS config files #13143
Comments
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days. |
I'm still interested in this. jest is the only thing pulling in ts-node in our stack, and it would be nice to be able to eliminate it for tsx. |
Making this pluggable would be nice - we had a PR at some point for an SWC-based loader as well. Thoughts on adding some sort of |
Sure, I think that adding a brief loader docblock at the top of the file would make sense, in the concept that within your dependency tree you end up with multiple TS loaders for whatever reason, and you want to make sure that you end up using a specific one, vs the default ordering of jest. Adding support for that should be pretty straight-forward, as compared to actually implementing these other loaders.
Do you know what it was named? I did find a PR for |
Edit: My bad, this is working on running the tests, not loading the config file |
I was trying to do this today and thought it would be as easy as adding NODE_OPTIONS='--experimental-vm-modules --loader @esbuild-kit/esm-loader' jest However, when I do that I get an interesting error:
Adding some logging to {
"type": "dependency",
"path": "file:///Users/linus/my-project/node_modules/jest-worker/build/workers/processChild.js"
} It seems like I'm not really sure how to continue debugging this, but would love some input! Generally, I think it would be amazing if Jest could work with the |
Okay, turns out the mysterious object above wasn't emitted from Jest at all, it was the loader. Filed an issue about that here: esbuild-kit/esm-loader#43 Knowing that I simply added this code to ignore the messages: }
_onMessage(response) {
+ // Ignore messages emitted by @esbuild-kit/esm-loader
+ // ref: https://github.com/esbuild-kit/esm-loader/issues/43
+ if (typeof response === 'object' && typeof response.type === 'string' && response.type === 'dependency') {
+ return
+ }
// TODO: Add appropriate type check
let error;
switch (response[0]) { This led me to the next problem.
Well, this stack trace was in Babel, and I didn't want to use that. So I added
This time the stack trace only shows Going in to this function it seems like it always loads the file from disk and passes it thru a function that calls the transformers. I tried replacing it with just an import of the file instead, something like: return core;
}
- const transformedCode = await this.transformFileAsync(modulePath, {
- isInternalModule: false,
- supportsDynamicImport: true,
- supportsExportNamespaceFrom: true,
- supportsStaticESM: true,
- supportsTopLevelAwait: true
- });
+ const transformedCode = `import '${modulePath}'`;
try {
const module = new (_vm().SourceTextModule)(transformedCode, {
context, This results in the following error though:
Lets just try calling my loader here directly and see if it works: return core;
}
- const transformedCode = await this.transformFileAsync(modulePath, {
- isInternalModule: false,
- supportsDynamicImport: true,
- supportsExportNamespaceFrom: true,
- supportsStaticESM: true,
- supportsTopLevelAwait: true
- });
+ const esmLoader = await import('@esbuild-kit/esm-loader')
+ const transformedCode = (await esmLoader.load(`file://${modulePath}`, { format: 'esm' }, (url) => {
+ return { source: fs().readFileSync(new URL(url), 'utf8') }
+ })).source
try {
const module = new (_vm().SourceTextModule)(transformedCode, {
context,
Success! Okay, if there is a way to get ahold of the loader some way I think using it to load files would be viable. @SimenB would there be any interest in maybe adding a flag for Jest that makes it use the loader that Node.js uses to load test files? I think that this would be awesome since we can run the tests in the same way that we run the normal code! edit: edit2: hmm, no every file is passed thru here I think, via the |
I'd be interested in a PR that shows the changes needed. 👍 |
Here it is! 🎉 |
#13521 wouldn't address the issue of how jest loads the config file though, just how it transforms and runs the test files right? |
@MasterOdin it seems like you are right, I will make a small update to address that 👍 In fact, I didn't notice that this issue was talking about config file specifically at all 😅 |
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days. |
(not stale) |
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days. |
(not stale) |
Still happy to take a PR adding support for some sort of docblock to the config file if anyone's up for it in the new year 😀 |
@SimenB Trying to find time to do this now, but to be clear on your comments on this thread as well as in #12041 and #11989 is that if the user does not specify a docblock, then jest will only try to use |
Yeah, that sounds about right. 👍 We can probably remove built-in ts-node in next major and have that also be opt-in via a docblock. |
Also, not sure if we should define som "config loader" interface (just |
ts-node hasn't seen a release in over a year at this point and still doesn't support TypeScript 5.0's multiple inheritance feature for
@MasterOdin, I believe it was #13779. |
It's worth to mention |
Heck yeah, man!!! Figured out how to get all tests passing, just by instead running them on the built version of the TS code, rather than the transpiled version of it. It's not as ideal as having it just work, but I can do that later, once things are migrated properly. Now the built TS source is put to the `./dist` folder as well, which is where the tests/mocks run from now instead. Yoo!!! jestjs/jest#13143 (Kind of helped a bit, but still ran into other issues, so I went with this route instead)
Heck yeah, man!!! Figured out how to get all tests passing, just by instead running them on the built version of the TS code, rather than the transpiled version of it. It's not as ideal as having it just work, but I can do that later, once things are migrated properly. Now the built TS source is put to the `./dist` folder as well, which is where the tests/mocks run from now instead. Yoo!!! jestjs/jest#13143 (Kind of helped a bit, but still ran into other issues, so I went with this route instead)
Any news on this? Or workarounds? As far as I understand, the problem is that Also, is this problem with |
Sadly, I give up with jest to handle typescript and esm. Migrated to vitest solve all the problems. |
Stil trying to see if I can move over to the built-in Node test runner instead of Jest, it didn't work the first time I tried moving to it. It doesn't have code coverage support, at least that I'm aware of, so I'm removing it in the Jest one first to help prevent accidental difference concerns. I started moving everything to TypeScript, but I really don't like how complex Jest is to use with either TS or plain ESM, so I want to use `tsx` with the Node test runner instead, that's a very nice and simple setup, I really like it. jestjs/jest#13143
🚀 Feature Proposal
I would like to be able to use the
tsx
compiler for handling thejest.config.ts
file, as opposed to relying on ts-node.Motivation
tsx
is a quickly rising alternative to ts-node as it runs much faster as it runs on the back of esbuild, and doesn't do typechecking. While parsing the jest configuration file should already be generally quick, it could be made quicker to using tsx. Additionally, for teams that have moved to tsx, it would allow having just one runtime compiler in their dependency for everything, vs having tsx for most things, and ts-node just for readingjest.config.ts
files.Example
It would be used implicitly within
jest-config
library where when it detects a file that ends with.ts
, it checks if ts-node is available and uses that, else it'll check for tsx and use that. If neither are available output an error message that neither could be found.All the user would need to do would be to have
tsx
installed via their package manager and available vianode_modules
.Pitch
Looking at https://github.com/facebook/jest/blob/main/packages/jest-config/src/readConfigFileAndSetRootDir.ts, there didn't seem to be an obvious way to modify the behavior of how it loads config files, where even if it was possible to get tsx registered before triggering jest-config, it would still attempt to use ts-node for
.ts
extension.The text was updated successfully, but these errors were encountered: