-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
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
Inconsistency with TypeScript in Module Resolution with Fully-Specified ESM Imports #13252
Comments
Alternately, in case @sokra or others decide that parity with TypeScript's module resolution algorithm with fully-specified ES Modules imports is not a goal of webpack, this bug / feature request may actually be better placed in the two loaders that were used to consume TypeScript (and which failed to replicate the TypeScript module resolution algorithm):
|
Hmm... as a workaround in the meantime, would it be possible to create a map of |
What is problem with webpack here? If you use |
The problem is that using the fully-specified With TypeScript and
With webpack, it fails and cannot resolve the See @RyanCavanaugh's comment here: microsoft/TypeScript#41887 (comment)
|
I think related TypeStrong/ts-loader#1198 |
Maybe somewhat related, although it seems this person is describing the opposite: they want to write node-style specifiers (without the extension) and have them resolved to the What we're looking for is to be able to write standard imports using ES Modules fully-specified import paths (with |
Give me time to look at this. I think problem somewhere here https://github.com/TypeStrong/ts-loader/blob/main/src/resolver.ts |
Anyway why do you want to use |
The TypeScript team doesn't agree, check out the issue I linked above: microsoft/TypeScript#41887 (comment) |
Yep, I see...
We need improve it on ts-loader side, webpack works correctly here. |
Thanks for the confirmation, I've opened an issue in |
Simple workaround for your simple case: resolve: {
alias: {
'./test.js': './test'
},
extensions: ['.tsx', '.ts', '...'],
}, Ideally To avoid collisions between resolve: {
byDependency: {
typescript: {
extensions: ['.tsx', '.ts', '...'],
},
} It will be implement using https://webpack.js.org/api/loaders/#thisgetresolve, we use the same logic for Honestly it's not hard to do. |
/cc @johnnyreilly make sense to look at this |
Simple: we should not do this https://github.com/TypeStrong/ts-loader/blob/main/src/resolver.ts, instead we should use Plus no problems with future major webpack versions and no need to have |
another workaround I found was using module.exports = function (env) {
return {
plugins: [
new webpack.NormalModuleReplacementPlugin(new RegExp(/^\..+\.js$/), function (resource) {
resource.request = resource.request.replace(new RegExp(/\.js$/), '');
}),
}
),
],
};
}; in our case, this did the trick Updated with the RegExp suggested by @laverdet #13252 (comment) |
Yep, should works too, anyway will be better to solve it in |
Yeah I think |
Something like that could be solved in a custom resolver plugin. I think think this typescript-specific problem fits into the webpack core. The resolver plugin could take an |
Cool - perhaps that's a better place for it to go! |
This issue had no activity for at least three months. It's subject to automatic issue closing if there is no activity in the next 15 days. |
not stale |
Would also be good to document in this thread here what version of |
Accidentally close, yes, you can specify |
technically we can add this to default rules but webpack doesn't support ts out of the box.. so probably you will need specify extension alias |
Alright, so the configuration is going to be something like this I assume: module.exports = {
resolve: {
extensionAlias: {
'.js': ['.ts', '.js'],
'.mjs': '.mts',
'.cjs': '.cts',
},
},
} One thing that's not quite clear about this is the inconsistent inclusion of the non-transformed extensions. In the first line, the So a more consistent configuration would be like this below (every value also including the non-transformed extensions): module.exports = {
resolve: {
extensionAlias: {
'.js': ['.ts', '.js'],
'.mjs': ['.mts', '.mjs'],
'.cjs': ['.cts', '.cjs'],
},
},
} However, ideally the non-transformed extension would be automatically included as a fallback in all configurations, so that this would work (no arrays with non-transformed extensions needed anywhere): module.exports = {
resolve: {
extensionAlias: {
'.js': '.ts',
'.mjs': '.mts',
'.cjs': '.cts',
},
},
} |
I tweaked the RegExp here because otherwise imports to modules like sha.js will fail. Thanks! new NormalModuleReplacementPlugin(/^\..+\.js$/, resource => {
resource.request = resource.request.replace(/\.js$/, "");
}), |
Yeah, sometimes I think npm should not allow to use
Do we load |
Looks like this is in version v5.74.0 |
The regex on the tweaked version doesn't seem right to me. Neither My suggestion would be use A better way to cover all cases would be tweaking the function in e.g. new NormalModuleReplacementPlugin(/.*\/+.+\.js$/, (resource) => {
if (/^sha\.js$/.test(resource.request) return; // - Exclude the edge cases using if statement
resource.request = resource.request.replace(/\.js$/, '');
}), Maybe we can also develop a plugin to do what we're doing with Edited for typo |
@iamWing the > /^\..+\.js$/.test('./app.js')
> true |
My bad for the typo, I actually mean The reason I'm using |
I've also opened a corresponding issue in Next.js, since it seems that they have their own flavor of the problem: |
@karlhorky Can you look at the latest version? |
Oh sorry, deleted my comment now! Indeed the type is there in |
I think we can close it, now we have |
…as problem since that's what typescript wants for transpilation; for more info, see: webpack/webpack#13252) * Added UI (and example data) for equivalent of "timeline system", where as you progress in time, different nodes get "focused". (prepwork for a scroll-and-zoom system within tree-grapher)
Use
/** @type {import("next").NextConfig} */
const nextConfig = {
experimental: {
// Remove .js from import specifiers, because
// Next.js and webpack do not yet support
// TypeScript-style module resolution out of the box
// https://github.com/webpack/webpack/issues/13252#issuecomment-1171080020
// https://github.com/vercel/next.js/pull/45423
// https://github.com/vercel/next.js/issues/58805
// https://github.com/vercel/next.js/issues/54550
extensionAlias: {
'.js': ['.ts', '.tsx', '.js', '.jsx'],
'.jsx': ['.tsx', '.jsx'],
'.mjs': ['.mts', '.mjs'],
'.cjs': ['.cts', '.cjs'],
},
},
}
module.exports = nextConfig |
Bug report
What is the current behavior?
When using extention .js as part of an import (fully-specified ESM import), webpack fails to create a bundle if the file imported have extention .tsx
This shouldnt be like this based on the comment of RyanCavanaugh
in this issue microsoft/TypeScript#41887 (comment)
If the current behavior is a bug, please provide the steps to reproduce.
I created a repo showing this unexpected behavior
this repo was tested with both
ts-loader
andbabel-loader
https://github.com/Josehower/webpack-babel-test
$yarn start
$yarn tsc --noEmit
What is the expected behavior?
In the example repo
yarn start
should succesfully create a bundle.Webpack should be able to recognize the files imported and create a bundle even if the import statements with the extention .js point files that have the extention .tsx
Other relevant information:
The text was updated successfully, but these errors were encountered: