react: Bug: Cannot import 'react/jsx-runtime' from esm node/webpack 5

React version: 17.0.1

Steps To Reproduce

  1. Create a new directory, cd to it.
  2. Run npm i react@17 webpack@5 webpack-cli@4
  3. Create index.mjs with the following content:
    import * as jsx from 'react/jsx-runtime';
    console.log(jsx);
    
  4. Run node index.mjs
  5. Run npx webpack-cli path/to/index.mjs
    • I had to use an absolute path on my machine or webpack-cli wouldn’t find index.mjs, don’t know why.

Link to code example: –

The current behavior

> node index.mjs
node:internal/process/esm_loader:74
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'D:\repos\jsx\node_modules\react\jsx-runtime' imported from D:\repos\jsx\index.mjs
Did you mean to import react/jsx-runtime.js?
    at new NodeError (node:internal/errors:277:15)
    at finalizeResolution (node:internal/modules/esm/resolve:307:11)
    at moduleResolve (node:internal/modules/esm/resolve:742:10)
    at Loader.defaultResolve [as _resolve] (node:internal/modules/esm/resolve:853:11)
    at Loader.resolve (node:internal/modules/esm/loader:85:40)
    at Loader.getModuleJob (node:internal/modules/esm/loader:229:28)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:51:40)
    at link (node:internal/modules/esm/module_job:50:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}
> npx webpack-cli D:\repos\jsx\index.mjs
[webpack-cli] Compilation finished
assets by status 264 bytes [cached] 1 asset
./index.mjs 64 bytes [built] [code generated]

ERROR in ./index.mjs 1:0-41
Module not found: Error: Can't resolve 'react/jsx-runtime' in 'D:\repos\jsx'
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.

webpack 5.4.0 compiled with 1 error in 150 ms
npm ERR! code 1

The expected behavior

No issues importing react/jsx-runtime with no file extensions.

I can think of two solutions:

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 34
  • Comments: 31 (2 by maintainers)

Commits related to this issue

Most upvoted comments

For anyone running into this issue, until a fix is released, I also encountered this, and found a way to resolve it.

In my case, I have a few React components exposed from internal packages published to our npm repo. Each component is written in TypeScript, and the published package contains the transpiled files, which already contain the react/jsx-runtime import. These components are then used in a React application, also written in typescript, which is then compiled using webpack v4. When running webpack for the application, I got the Module not found: Error: Can't resolve 'react/jsx-runtime' in '.../app/node_modules/@components/Component/src/index' error, similar to the one in this issue.

To fix this, I added 'react/jsx-runtime': require.resolve('react/jsx-runtime'), to my webpack configuration’s resolve.alias field.

@Andarist The issue isn’t in .mjs extension, but in a ESM package. If you read the error it says:

or a '*.js' file where the package.json contains '"type": "module"'

My files are just .js and, of course, I’ve got the error. All file imports of ESM packages should have extensions by the spec.


Alternative way to specified in https://github.com/facebook/react/issues/20235#issuecomment-732205073 is to just add the extension manually:

resolve: {
  alias: {
    "react/jsx-dev-runtime": "react/jsx-dev-runtime.js",
    "react/jsx-runtime": "react/jsx-runtime.js"
  }
}

In the repo I work on, we’ve started publishing the library using the new runtime, using rollup+babel. If you install it (npm install react-data-grid), and check node_modules/react-data-grid/lib/bundle.js, you’ll see the import:

import { jsxs, jsx, Fragment } from 'react/jsx-runtime';

Some bundlers like webpack 4 or rollup are fine with it, but webpack 5 adopted the newer Node semantics regarding esm, so it expects either a full path with file extension, or react/jsx-runtime to be matched in an exports map. It’s also an issue in Node if you try to do server-side rendering from an esm file.

IMO adding an exports map should be a quick and safe enough fix. There are multiple transformers that would need fixing otherwise: Babel, TypeScript 4.1, more? I can go back to the classic runtime so it’s not a major issue, but it needs to be fixed upstream one way or the other eventually.

The react/jsx-runtime import is added by the babel preset, I just showed a simplified example for quick bug reproduction.

It can be easily fixed with a simple exports map in package.json:

{
  "type": "commonjs",
  "exports": {
    ".": "./index.js",
    "./jsx-dev-runtime": "./jsx-dev-runtime.js",
    "./jsx-runtime": "./jsx-runtime.js",
    "./": "./"
  },
}

This is fixed in React 18.

In addition to https://github.com/facebook/react/issues/20235#issuecomment-1018305042, I suggest not to use alias, this will be breaking again when 7.0.3 is published, use fallback instead:

resolve: {
    fallback: {
        'react/jsx-runtime': 'react/jsx-runtime.js',
        'react/jsx-dev-runtime': 'react/jsx-dev-runtime.js',
    },
},

This will successfully resolve in 7.0.3 and 18.x and fallbacks to *.js when they are not importable.

I faced the same problem by using creat-react-app.

@gaearon Are React 17 and 16 not supported anymore?

I just ran into this issue with react not specifying exports in react@17.0.2, which caused the build to fail using next@11.1.0 in combination with react-data-grid@7.0.0-beta.2. Issue described further in https://github.com/adazzle/react-data-grid/issues/2568#issuecomment-901165249

By using yarn patch to apply the fields described in https://github.com/facebook/react/issues/20235#issuecomment-728824662 fixed the issue completely.

Would be fantastic if this could be patched in for React 17.

The alphas of React 18 have the exports field, so at least this issue will be fixed when 18.0.0 is released.

I’m reposting this comment of mine from the Babel’s tracker but I adjust it slightly to fit better here. You can read it here or in the linked thread.


Adding extensions in the emitted code is being problematic for a couple of reasons and I believe that it should be avoided. I understand that it’s unfortunate that things break right now because of it - but node’s semantics are very new. The ESM support in node has been released just this month - so it’s understandable that some packages are not yet ready in full for it.

The solution for this would be indeed to add exports map like in this PR: https://github.com/facebook/react/pull/20304 . It was already a great gesture from the React team to ship runtimes for all~ React versions. I suppose they could add exports map in a similar fashion to all of them, just to avoid confusion etc. It makes sense given how many users they have but it’s not up to me to decide about this.

As to the current webpack’s situation - just don’t use .mjs for now. If you rename your file to .js then webpack will gladly resolve the react/jsx-runtime entrypoint. You just don’t have to opt-into the new node’s semantics right away and just give time for this issue here to be resolved.

“Unsafe” as in it will be a breaking change for someone else despite it being a minor release.

What do you mean by “supported”? If there is a security issue, we release a fix for all majors. For other cases, we don’t typically release updates to non-current majors. In this particular case, we don’t believe backporting would even be safe — ESM configurations and setups are very fragile — so we don’t think it’s safe to do in 17 even if it was actively released.

For people using the recently releasedcreate-react-app@5.0.0, there’s currently an ongoing pull request #11797, expected for the 5.0.1 release.

Until then, here’s a solution:

  1. Install patch-package, which allows you to modify node_modules dependency directly in the code - and keep the modification available even after running a fresh npm install. yarn add patch-package postinstall-postinstall
  2. Add a postinstall hook to your projects package.json scripts "postinstall": "patch-package"
  3. Open the node_modules/react-scripts/config/webpack.config.js in your code editor, scroll to about line 320 with the alias and add:
      alias: {
+      "react/jsx-dev-runtime": "react/jsx-dev-runtime.js",
+      "react/jsx-runtime": "react/jsx-runtime.js",
        // Support React Native Web
        // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
        'react-native': 'react-native-web',
        // Allows for better profiling with ReactDevTools
        ...(isEnvProductionProfile && {
          'react-dom$': 'react-dom/profiling',
          'scheduler/tracing': 'scheduler/tracing-profiling',
        }),
        ...(modules.webpackAliases || {}),
      },
  1. Apply the patch with yarn patch-package react-scripts. This will now create a patch directory in your project root, with the patch file.

Now the patch is available even after a fresh installation. Also, set a reminder to check for pull request #11797 release to remove the patch. Removing the patch is pretty straightforward. Remove patch-package postinstall-postinstall, remove the package.json script & delete the /patch dir (if you don’t use patch-package for anything else).

I am running into the following issue at our company due to the file resolution pointing to a file using require statement when attempting to resolve as an esm module. The problem is specific to yarn 3 I believe but their solution is simply trying to resolve files based on module support. I expect this will present itself beyond yarn 3 (or may have already). Also complicated because the jsx-runtime import statement is actually coming through @emotion/core so in this case it’s a transitive dependency for the projects of concern.

Is this a problem already solved in react 17? image

For anyone running into this issue, until a fix is released, I also encountered this, and found a way to resolve it.

In my case, I have a few React components exposed from internal packages published to our npm repo. Each component is written in TypeScript, and the published package contains the transpiled files, which already contain the react/jsx-runtime import. These components are then used in a React application, also written in typescript, which is then compiled using webpack v4. When running webpack for the application, I got the Module not found: Error: Can't resolve 'react/jsx-runtime' in '.../app/node_modules/@components/Component/src/index' error, similar to the one in this issue.

To fix this, I added 'react/jsx-runtime': require.resolve('react/jsx-runtime'), to my webpack configuration’s resolve.alias field.

@roikoren755

Any chance you could add your whole webpack config?

I have this for my next config and it doesn’t appear to work still:

    if (!isServer) {
      config.resolve.fallback.fs = false;
    }
    config.resolve.alias = {
      ...config.resolve.alias,
      "react/jsx-dev-runtime": "react/jsx-dev-runtime.js",
      "react/jsx-runtime": "react/jsx-runtime.js",
    };

    return config;
  }

I just showed a simplified example for quick bug reproduction.

Could you show an example that uses the jsx-runtime as it’s intended? That would help identify the solution better. For example, a fix could be applied to the transformer instead.