You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[TS 4.1] react-jsx breaks a type:module package #41623
The react/jsx-runtime has no extension. Which breaks Webpack 5 (5.6).
Module not found: Error: Can't resolve 'react/jsx-runtime' in 'project'
Did you mean 'jsx-runtime.js'?
BREAKING CHANGE: The request 'react/jsx-runtime' failed to resolve only because it was resolved as fully specified (probably because the origin is a '.mjs' file or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
changed the title [-][TS 4.1] Using jsx:react-jsx breaks a type:module package[/-][+][TS 4.1] Using react-jsx breaks a type:module package[/+]on Nov 21, 2020
Nope! The current behavior is expected - You're using a version of a runtime (well, webpack) that doesn't (fully?) support exports maps (or your specific version of the react package is missing them), which is what allows the extensionless imports to function - the transform, canonically, produces imports without extensions. There was a big todo about this over on the babel repo a few months ago, where the behavior got flip-flopped across the ecosystem (we tried adding extensions, this broke preact and friends who'd already adopted exports maps successfully, then had to go back to not adding extensions) (and if you disagree, you should probably open an issue on the babel/react issue trackers, since we're just trying to match them).
I understand the point, but using the exports map seams like a last resort and of course it is an implementation detail of the consumed package on which the consumer has no control.
For example:
I'm consuming React, I can't force the React team to map an import to react/jsx-runtime into react/jsx-runtime.js in their package.json file.
They could simply argue, "well man, just import the right file" and they would be right.
As you can see here, they do not use the exports map. https://github.com/facebook/react/blob/v17.0.1/packages/react/package.json
Technically speaking, a configuration flag/option should configure something.
I'm not saying that using by default the '.js' extension is right or a mistake, but that the tsc compiler, given an already present jsxImportSource option, should be configurable by the developer to emit what the developer wants.
If for some reasons it is not possible to exploit the already present jsxImportSource, it would just easy as introducing an option like jsxImportPath where the developer can instruct the tsc compiler to emit what the developer needs.
Example:
jsxImportPath: "react/jsx-runtime.js"
It does not break anything, it works with "legacy" packages without an export map and does not need a runtime able to remap the imports.
Reacted by Jeswin, Andrew Zolotukhin and Jean-Yves Moyen
I'm trying to transpile React 17.0.2 with TypeScript configured to use "module": "ES6" (rather than "CommonJS").
To get the output to run in Node, for now seems you have to manually update node_modules/react/package.json and add this configuration, reproduced here:
I think it's incorrect for typescript to be emitting CJS code when tsconfig.json instructs it to emit ES modules compatible code.
It can be solved in bundlers with various configuration options, but it creates problems in various server-side rendering usecases. I needed the following hack while invoking node:
# Affects all imports, so not ideal.
node --experimental-specifier-resolution=node yourscript.js
When I look at the corresponding babel thread, it seems they did the right thing initially and then reverted because it broke preact. IMHO typescript should emit clean output, or at least make it configurable.
Right now, it looks like there is no way to get clean ES modules compatible output while using tsx.
Activity
daniele-orlando commentedon Nov 21, 2020
For others utility, this is my fix at the moment:
Quite ugly. 😢
[-][TS 4.1] Using jsx:react-jsx breaks a type:module package[/-][+][TS 4.1] Using react-jsx breaks a type:module package[/+][-][TS 4.1] Using react-jsx breaks a type:module package[/-][+][TS 4.1] react-jsx breaks a type:module package[/+]weswigham commentedon Nov 26, 2020
Nope! The current behavior is expected - You're using a version of a runtime (well, webpack) that doesn't (fully?) support
exportsmaps (or your specific version of thereactpackage is missing them), which is what allows the extensionless imports to function - the transform, canonically, produces imports without extensions. There was a big todo about this over on the babel repo a few months ago, where the behavior got flip-flopped across the ecosystem (we tried adding extensions, this broke preact and friends who'd already adopted exports maps successfully, then had to go back to not adding extensions) (and if you disagree, you should probably open an issue on the babel/react issue trackers, since we're just trying to match them).daniele-orlando commentedon Nov 26, 2020
Thank you very much Wesley Wigham (@weswigham) for the extensive explanation.
I understand the point, but using the exports map seams like a last resort and of course it is an implementation detail of the consumed package on which the consumer has no control.
For example:
I'm consuming React, I can't force the React team to map an import to
react/jsx-runtimeintoreact/jsx-runtime.jsin their package.json file.They could simply argue, "well man, just import the right file" and they would be right.
As you can see here, they do not use the exports map.
https://github.com/facebook/react/blob/v17.0.1/packages/react/package.json
Technically speaking, a configuration flag/option should configure something.
I'm not saying that using by default the '.js' extension is right or a mistake, but that the tsc compiler, given an already present
jsxImportSourceoption, should be configurable by the developer to emit what the developer wants.If for some reasons it is not possible to exploit the already present
jsxImportSource, it would just easy as introducing an option likejsxImportPathwhere the developer can instruct the tsc compiler to emit what the developer needs.Example:
It does not break anything, it works with "legacy" packages without an export map and does not need a runtime able to remap the imports.
nicolo-ribaudo commentedon Nov 27, 2020
Reposting from the issue on the Babel side: soon React will only support the version without the extension: https://github.com/facebook/react/pull/20304/files#diff-1f344ac391eeecc21ec0f01fb07430a47f4b80d20485c125447d54c33c4bbfc4R34-R35
dtrelogan commentedon Apr 15, 2021
I'm trying to transpile React 17.0.2 with TypeScript configured to use "module": "ES6" (rather than "CommonJS").
To get the output to run in Node, for now seems you have to manually update node_modules/react/package.json and add this configuration, reproduced here:
daniele-orlando commentedon Apr 19, 2021
It will be fixed in React 17.0.3.
jeswin commentedon Aug 20, 2021
I think it's incorrect for typescript to be emitting CJS code when tsconfig.json instructs it to emit ES modules compatible code.
It can be solved in bundlers with various configuration options, but it creates problems in various server-side rendering usecases. I needed the following hack while invoking node:
# Affects all imports, so not ideal. node --experimental-specifier-resolution=node yourscript.jsWhen I look at the corresponding babel thread, it seems they did the right thing initially and then reverted because it broke preact. IMHO typescript should emit clean output, or at least make it configurable.
Right now, it looks like there is no way to get clean ES modules compatible output while using tsx.