Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Error: Cannot find module 'react/jsx-runtime'" when consuming Parcel's multi-module React component library in Next.js project created by "yarn create next-app" command #8069

Closed
Thienhuynh95 opened this issue May 8, 2022 · 13 comments

Comments

@Thienhuynh95
Copy link

Thienhuynh95 commented May 8, 2022

馃悰 bug report

Error "Cannot find module 'react/jsx-runtime'" happens when consuming Parcel's multi-module React component library in a Next.js project. I already spent a week just to fix this build, I really like developing Parcel API, so I really appreciate any help/suggestion to make this work 馃槩 . I tried to adjust engines in the parcel config, context field, add/remove targets, but it doesn't seem to work (it can build but Next.js couldn't consume it - alway get an error like "Can't find module '...'"), also when I include "react" in includeModules field or set includeModules to true, it produced the error "Can't have more than 1 copy of React...".

馃帥 Configuration (.babelrc, package.json, cli command)

.babelrc:

  • I don't have .babelrc in my project, I just use default babel configuration in @parcel/config-default.

package.json:

{
  "name": "reproduce-parcel-issue",
  "version": "1.0.0",
  "description": "Code configuration to reproduce parcel issue",
  "engines": {
    "node": ">= 12"
  },
  "browserslist": "> 0.5%, last 2 versions, not dead",
  "author": "Thien Huynh",
  "license": "MIT",
  "private": false,
  "devDependencies": {
    "@parcel/core": "^2.5.0",
    "@parcel/packager-ts": "2.5.0",
    "@parcel/transformer-typescript-tsc": "^2.5.0",
    "@parcel/transformer-typescript-types": "2.5.0",
    "@parcel/types": "^2.5.0",
    "@types/node": "^17.0.31",
    "@types/react": "17.0.41",
    "@types/react-dom": "17.0.13",
    "@types/styled-components": "5.1.24",
    "eslint": "7.32.0",
    "eslint-config-airbnb": "18.2.0",
    "eslint-config-airbnb-typescript": "^12.3.1",
    "eslint-config-prettier": "^6.11.0",
    "eslint-import-resolver-parcel2": "^1.0.1",
    "eslint-plugin-import": "2.25.4",
    "eslint-plugin-jest": "24.7.0",
    "eslint-plugin-jsx-a11y": "6.5.1",
    "eslint-plugin-prettier": "3.4.1",
    "eslint-plugin-react": "7.29.4",
    "eslint-plugin-react-hooks": "4.3.0",
    "eslint-plugin-simple-import-sort": "^7.0.0",
    "@typescript-eslint/eslint-plugin": "4.33.0",
    "@typescript-eslint/parser": "4.33.0",
    "dotenv": "^16.0.0",
    "postcss": "8.4.12",
    "postcss-preset-env": "6.7.1",
    "parcel": "^2.5.0",
    "prettier": "2.6.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-hotkeys-hook": "3.4.4",
    "react-is": "17.0.2",
    "react-tooltip": "4.2.21",
    "styled-components": "5.3.3",
    "ttypescript": "^1.5.13",
    "typescript": "4.6.2"
  },
  "resolutions": {
    "@types/react": "17.0.41",
    "@types/react-dom": "17.0.13"
  },
  "peerDependencies": {
    "framer-motion": "^4.x",
    "react": "^17.x",
    "react-dom": "^17.x",
    "react-hotkeys-hook": "^3.x",
    "react-is": "^17.x",
    "react-tooltip": "^4.x",
    "styled-components": "^5.x"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "scripts": {
    "prebuild": "rm -rf ./dist .parcel-cache && ttsc build.ts --outDir . --module es2022 --sourceMap true && mv build.js build.mjs",
    "build": "node build.mjs && yarn build:dts",
    "postbuild": "yarn build:prep:publish",
    "prebuild:dts": "echo 'building dts'",
    "build:dts": "ttsc --emitDeclarationOnly",
    "posbuild:dts": "echo 'done build dts'",
    "prebuild:prep:publish": "echo 'building for publishing'",
    "build:prep:publish": "ttsc src/setupPackage.ts --sourceMap false && mv dist/setupPackage.js ./dist/setupPackage.mjs && node dist/setupPackage.mjs",
    "postbuild:prep:publish": "echo 'done building for publishing'"
  },
  "exports": {
    ".": {
      "import": "./module/index.js",
      "node": "./module/index.js",
      "module": "./module/index.js",
      "default": "./index.js"
    },
    "./components/*": {
      "import": "./module/components/**/*.js",
      "node": "./module/components/**/*.js",
      "module": "./module/components/**/*.js",
      "default": "./components/**/*.js"
    },
    "./icons/*": {
      "import": "./module/icons/*.js",
      "node": "./module/icons/*.js",
      "module": "./module/icons/*.js",
      "default": "./icons/*.js"
    }
  }
}

build.ts: (parcel config)

{
    detailedReport: { assetsPerBundle: 20 },
    entries: 'src/index.ts' // or 'src/icons/*.tsx',
    targets: {
      main: {
        distDir: 'dist',
        context: 'browser',
        engines: {
          browsers: ['> 0.5%', 'last 2 versions', 'not dead'],
          parcel: '>2.5',
        },
      },
      module: {
        distDir: 'dist/module',
        context: 'node',
        engines: {
          node: '>= 12',
          parcel: '>2.5',
        },
      },
    },
    defaultTargetOptions: {
      isLibrary: true,
      sourceMaps: false,
      shouldOptimize: false,
      outputFormat: 'esmodule',
      engines: {
        parcel: '>2.5',
      },
    },
    shouldPatchConsole: true,
    shouldAutoInstall: true,
    shouldContentHash: false,
    additionalReporters: [
      {
        packageName: '@parcel/reporter-cli',
        resolveFrom: fileURLToPath(import.meta.url),
      },
    ],
    defaultConfig: '@parcel/config-default',
    mode: 'production',
  }

馃 Expected Behavior

No runtime exception. The library should be able to be consumed in the Next.js project.
Be able to import components from the reproduce-parcel-issue library in the Next.js project:

import { Button } from "reproduce-parcel-issue";
// or
import { Button } from "reproduce-parcel-issue/components/Button/Button"
// or
import { Anchor } from "reproduce-parcel-issue/components/Button/Anchor" 

馃槸 Current Behavior

Produced error "Cannot find module 'react/jsx-runtime'" when access to dev url localhost:3000 after ran yarn dev in Next.js project.

Stack traces:

Unhandled Runtime Error
Error: Cannot find module 'react/jsx-runtime'

Call Stack
newRequire
node_modules/reproduce-parcel-issue/module/index.js (61:0)
  
newRequire
node_modules/reproduce-parcel-issue/module/index.js (45:0)
  
localRequire
node_modules/reproduce-parcel-issue/module/index.js (84:32)
  
Object.2G6Uk.@parcel/transformer-js/src/esmodule-helpers.js
node_modules/reproduce-parcel-issue/module/index.js (169:0)
  
newRequire
node_modules/reproduce-parcel-issue/module/index.js (71:0)
  
localRequire
node_modules/reproduce-parcel-issue/module/index.js (84:32)
  
Object.gGjxz../Anchor
node_modules/reproduce-parcel-issue/module/index.js (161:0)
  
newRequire
node_modules/reproduce-parcel-issue/module/index.js (71:0)
  
localRequire
node_modules/reproduce-parcel-issue/module/index.js (84:32)
  
Object.XliwM../components/Button
node_modules/reproduce-parcel-issue/module/index.js (152:0)
  
newRequire
node_modules/reproduce-parcel-issue/module/index.js (71:0)
  
eval
node_modules/reproduce-parcel-issue/module/index.js (122:0)
  
eval
node_modules/reproduce-parcel-issue/module/index.js (145:1)
  
Object../node_modules/reproduce-parcel-issue/module/index.js
file:///Users/thienhuynh/test-next/.next/static/chunks/pages/index.js (454:1)
  
Object.options.factory
/_next/static/chunks/webpack.js (685:31)
  
__webpack_require__
file:///Users/thienhuynh/test-next/.next/static/chunks/webpack.js (37:33)
  
fn
/_next/static/chunks/webpack.js (354:21)
  
eval
webpack-internal:///./pages/index.js (11:80)
  
Module../pages/index.js
file:///Users/thienhuynh/test-next/.next/static/chunks/pages/index.js (117:1)
  
Module.options.factory
/_next/static/chunks/webpack.js (685:31)
  
__webpack_require__
file:///Users/thienhuynh/test-next/.next/static/chunks/webpack.js (37:33)
  
fn
/_next/static/chunks/webpack.js (354:21)
  
eval
node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?page=%2F&absolutePagePath=%2FUsers%2Fthienhuynh%2Ftest-next%2Fpages%2Findex.js! (5:15)
  
eval
node_modules/next/dist/client/route-loader.js (207:48)

馃拋 Possible Solution

I don't know if this is the issue with Parcel or Next.js configuration. Maybe making the right configuration options in the Parcel API to either generate the bundled script can be used on the client side (be able to use shared modules (react, react-dom, styled-components, ...) on the browser) or make Next.js to be able to consume the library directly (like importing it as if it's an internal code in Next.js project when the library's not bundled and minified) before building pages 馃拋

馃敠 Context

I'm trying to create a public multi-module React component library that would be consumed by the Next.js project. I want to separate the modules, so the consumers don't need to import everything when they just want to consume just one component in the big module. And the way I use Parcel to bundle in my mini project is by writing a script build.ts that use Parcel API.
The script build.ts will just loop through the module configs list and call Parcel API to bundle it.

馃捇 Code Sample

Repositories:

Step to reproduce:

yarn && yarn build
yarn && yarn dev

馃實 Your Environment

Software Version(s)
Parcel 2.5.0
Node 14.19.0
npm/Yarn Yarn (1.22.17)
Operating System MacOS

Update

With same configuration, I tried to bundle project with Rollup and it works perfectly when I use the library in the next project. I added building process for using Rollup.js to bundle in this repository Parcel bundling sample script on branch feat/rollup-test.

Step to reproduce:

  1. Clone this repository Parcel bundling sample script and switch branch to feat/rollup-test
  2. Run command below to install dependencies and build the library with rollup
yarn && yarn build:rollup
  1. Copy generated dist folder from "Parcel bundling sample script" project over the Next.js project, run command below in Next.js project's terminal to install local module in project's dependencies node_modules and build dev server:
yarn && yarn dev
@V3RON
Copy link

V3RON commented Jun 4, 2022

Actually that's not a problem with Parcel, but React itself. As far as I know it has been fixed in React v18, but unfortunately never backported to v17.

This import bug only occurs when using Webpack 5 as its resolving algorithm has been updated and now it expects either a full path with file extension or an entry in "exports" map. Neither is present in React v17.

See:
facebook/react#20235
vercel/next.js#27977

@Thienhuynh95
Copy link
Author

@V3RON Thanks for replying, I really appreciate that. I think that's not an issue 馃. Because with the same code I provided above, if I use rollup.js or webpack to bundle, it works just fine. Also, I just tried to upgrade react to 18 for both next and the library project. I still got the same issue.

@V3RON
Copy link

V3RON commented Jun 6, 2022

@Thienhuynh95 Could you share your Rollup/Webpack configuration? I would like to look into it. I'm really curious what's happening if it's really working in those, but not in Parcel. 馃

@Thienhuynh95
Copy link
Author

@V3RON Yes, absolutely, I'm happy to do that.
The example is on branch feat/rollup-test in Parcel bundling sample script. I've also updated the bottom in my issue's description above about the step to clone and run that rollup configuration example.
Please let me know if you need more information. Thanks a lot!

@V3RON
Copy link

V3RON commented Jun 6, 2022

@Thienhuynh95 Well, both branches work just fine on my side. Not sure why 馃し

However, I noticed your Rollup branch uses old react transform (tsconfig.json, "jsx" property) when Parcel automatically switches to the new one (react-jsx). Could you try updating tsconfig.json and switching from "react" to "react-jsx"? If Next will no longer be able to consume it, then it means my previous comment is valid.

@Thienhuynh95
Copy link
Author

Thienhuynh95 commented Jun 7, 2022

@V3RON I tried your suggestion, changed 'react' to 'react-jsx', but it's not working as it supposed to. And it's weird that you can't reproduce the issue 馃ゲ

@github-actions github-actions bot added the Stale Inactive issues label Dec 5, 2022
@Thienhuynh95
Copy link
Author

I gave up and switched over to rollup. I will close this ticket. Thanks everyone for helping, I really appreciate it.

@github-actions github-actions bot removed the Stale Inactive issues label Dec 5, 2022
@djuretic
Copy link

djuretic commented Dec 7, 2022

Even though this issue is closed, I want to comment about what worked for me.

I was having both Failed to resolve 'react/jsx-runtime' and External dependency "react" is not declared in package.json errors, moving react and some other packages from devDependencies to dependencies in package.json solved the errors.

@Thienhuynh95
Copy link
Author

Thienhuynh95 commented Dec 7, 2022

@djuretic I think react should not be in dependencies and the library built by Parcel should use whichever the react version on the consumer project, because I use Parcel in order to build the library, and if react is the dependency, it may cause an error since it initiates more than 2 react instances in the same app.

@kirilsvoloshins
Copy link

is there a solution to this?
can not even create a simple react typescript app using parcel :(

@tylerlong
Copy link

As I tested, parcel [server] works like a charm while parcel build has this issue:

馃毃 Build failed.

@parcel/core: Failed to resolve 'react/jsx-runtime' from './src/app.tsx'

...

@parcel/resolver-default: External dependency "react" is not declared in 
package.json.

@mischnic
Copy link
Member

@tylerlong Are you building a library or a webapp? For a webapp, you should never see External dependency .... is not declared, so that's a configuration issue. Do you have a main field in your package.json?

@tylerlong
Copy link

@tylerlong Are you building a library or a webapp? For a webapp, you should never see External dependency .... is not declared, so that's a configuration issue. Do you have a main field in your package.json?

It's complicated. It's an electron app with both webapp part and node.js part. It does have a main field because electron requires it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants