-
-
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
Support for using native Node ESM loader #13521
Conversation
Pushed a small fix that makes it work with |
Pushed another small fix that uses the built in loader to load the config file as well 🎉 edit: didn't actually pushed it, but pushed now 🙈 |
2048b4b
to
c96b1c9
Compare
(rebased on #13543) |
c96b1c9
to
569a630
Compare
(rebased on #13543) |
@SimenB @privatenumber @mariocandela Is there anything that can be done from my side to move forward with this? |
@SimenB @privatenumber @mariocandela Would love to move forward with this! Anything I can do from my side? |
Nothing more from me, but I appreciate that you keep pushing. I think you'll want to ping @SimenB directly as he's the maintainer. |
@LinusU Thanks for taking a crack at this. Being able to use any loader will be helpful and a step in the right direction. One thing I'm wondering is whether you ran through any scenarios using tsconfig path mapping? With tsx supporting that out of the box, I think any solution here would likely need to also support that functionality. I might be out of my element here, but from evaluating tsx's code base, it seems that the path mapping works via the I might be way off base here, and everything you've proposed might work fine there, but I thought it would be worth broaching the subject in case it wasn't considered. The other thing that comes to mind here is the possibility that multiple loaders have been specified. If I'm following your solution correctly, only the first loader will be processed. That would likely cover a huge percentage of any use case for loaders, but there could be scenarios where multiple loaders are necessary and it would not work. Thanks again for your efforts to land this improvement! |
Happy to help! 🙏
I haven't personally used tsconfig path mapping, but you're probably right in that they wouldn't work. However, I'm not sure that they work when using So if my hunch is correct, I'm not sure that it's inside the scope to support this, since this is about supporting any
This is not supported currently, but should probably be quite easy to add in. Would prefer to do it in a follow up PR though to limit the scope of this one.
❤️ |
569a630
to
0b11099
Compare
(rebased on latest master) |
0b11099
to
a873c25
Compare
@SimenB I think that the only thing I need in order to take this out of the draft stage is some input on how this should be activated. The code currently checks if there is a However, I'm thinking that this could be a breaking change if someone is currently passing in a loader and relying on it not being picked up. Another option could be to add a Do you have any input on this? |
tsx uses https://github.com/esbuild-kit/esm-loader as the loader, which supports tsconfig paths: |
@privatenumber thanks for the link! It seems like one more improvement here would be to support the Personally, I would prefer it if that would be done in a follow up to keep this PR as tight in scope as possible. But if this is deemed as required in order to support loaders than we can add it here. To keep track, there is currently two "extra" features that would be nice:
|
It seems like the linting rules was recently updated, I had to make the following changes to make it happy, but I'm not sure that it is desirable. Maybe I misunderstood something? __: string,
___: ReducedTransformOptions,
): Promise<TransformResult> {
- throw new Error(
- '`transformSourceAsync` should not be called when using --loader',
+ return Promise.reject(
+ new Error(
+ '`transformSourceAsync` should not be called when using --loader',
+ ),
);
} url,
{format: 'module', importAssertions: {}},
async () => {
- return {format: 'module', source: fileSource};
+ return Promise.resolve({format: 'module', source: fileSource});
},
); These two are async functions, but they don't use );
}
- return await requireOrImportModule(moduleName);
+ return requireOrImportModule(moduleName);
}
} Removing More info about this: https://github.com/goldbergyoni/nodebestpractices#-212-always-await-promises-before-returning-to-avoid-a-partial-stacktrace |
a873c25
to
f82bfe1
Compare
@LinusU it's a nice concept, but I'm afraid it looks like a complicated hack to do simple thing: use custom transformer. In other words, you can create transformer.mjs in ~40 lines of code to use any ESM loader just by importing it. With some helper library it might look like this: // transformer.mjs referenced in jest config
import {wrapper} from 'jest-esm-loader-support';
import {resolve, load} from 'any modern ESM loader';
export default wrapper(resolve, load); Moreover, because you can pass options to the transformer via https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object, it doesn't need to write any code: {
transform: {
"\\.ts$": [require.resolve('jest-esm-loader-support-v2'), {loader: 'any modern ESM loader'}]
},
} Sure, you can implement a hacky logic to load currently applied loader (which of them in case of more than 1 loader used?) too if 'loader' parameter is omitted :) |
Hm.. Not sure if transformer would be enough. Config files are not passed through transformers, because it is not yet clear which transformers will be needed. |
We have 3 type of entities here:
Anyway, we just can't grab loader module specifier from argv, import & use it - because loader chaining already landed in Node. It will work only for simple scenarios with 1 loader. For more complex - not, especially if we don't want to re-implement lib/internal/modules/esm/hooks.js logic. |
This PR is stale because it has been open 1 year with no activity. Remove stale label or comment or this will be closed in 30 days. |
This PR was closed because it has been stalled for 30 days with no activity. Please open a new PR if the issue is still relevant, linking to this one. |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
As previously discussed in #13143, this PR shows roughly what changes would be needed in order to support Node.js
--loader
. I'm opening this as a draft PR since I would need guidance on where the code should live, how the code should be activated by the user, and how to create tests for it.ping @SimenB
I would be very happy to receive any feedback, or to discuss how this could/should work!
Test plan
I've tested this by running
yarn build
and manually coping the changed files into another small test project 🙈package.json
foobar.test.ts
I have currently only tested this with
@esbuild-kit/esm-loader
, but the goal is that it should work with any--loader