vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.88k stars 26.97k forks source link

Import ESM Externals Error only when linking a local package #34956

Open monsonjeremy opened 2 years ago

monsonjeremy commented 2 years ago

Verify canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 21.3.0: Wed Jan  5 21:37:58 PST 2022; root:xnu-8019.80.24~20/RELEASE_ARM64_T8101
Binaries:
  Node: 16.13.0
  npm: 8.5.2
  Yarn: 1.22.15
  pnpm: 6.32.2
Relevant packages:
  next: 12.1.1-canary.5
  react: 17.0.2
  react-dom: 17.0.2

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

I have a package in my node_modules which uses an ESM package (is-stream@^3.0.0). The package using the ESM package is trying to require it which I know is an error and I have raised an issue in the downstream package here. This is fine as next offers a great option experimental.esmExternals: 'loose' in order to fix this issue.

The bug that I have noticed is that so long as I have installed the package (in my example it's @monsonjeremy/esm-external-package) I don't even need to enable experimental.esmExternals: 'loose', I am able to run the application just fine without getting this error. If however I link to the package locally, then I get the error:

ESM packages (is-stream) need to be imported. Use 'import' to reference the package instead. https://nextjs.org/docs/messages/import-esm-externals

I am really confused why linking has different behavior then installing the package from NPM and if this is expected.

Expected Behavior

I should have uniform behavior when linking the package locally or installing it from NPM.

To Reproduce

I have created an example repo here, which can be used to see the issue: https://github.com/monsonjeremy/esm-external-example-repo

Steps:

  1. Clone the repo
  2. Run cd example-package
  3. Run npm install && npm run build && npm link
  4. Now go to the next app directory cd ../example-app
  5. Run npm install 6: Run npm run dev
  6. See that the page is able to load as expected on localhost:3000
  7. Stop the server and run npm link @monsonjeremy/esm-external-package
  8. Restart the server with npm run dev
  9. See that localhost:3000 now has an error:
    ESM packages (is-stream) need to be imported. Use 'import' to reference the package instead. https://nextjs.org/docs/messages/import-esm-externals
monsonjeremy commented 2 years ago

This seems to reproduce inconsistently, i've noticed if I change swcMinify from false to true or vice versa it'll cause the issue.

eric-burel commented 2 years ago

I might have a similar issue with Babel setup, I get the issue with Yalc. I should try with an alpha release of the packages later on. To be more precise: I own package A and B, both have an exports like this:

{
  "name": "@vulcanjs/graphql",
  "version": "0.5.3",
  "main": "./dist/index.js",
  "files": [
    "dist/"
  ],
  "type": "module",
  "exports": {
    ".": {
      "node": "./dist/index.cjs",
      "import": "./dist/index.js"
    },
    "./testing": {
      "node": "./dist/testing.cjs",
      "import": "./dist/testing.js"
    },
    "./server": "./dist/server/index.cjs"
  },
  "types": "./dist/index.d.ts",
  "typesVersions": {
    "*": {
      "server": [
        "./dist/server/index.d.ts"
      ],
      "testing": [
        "./dist/testing.d.ts"
      ]
    }
  },

I am using "Yalc publish" so it's normally a copy and not a symlink like with Yarn link.

I use Next 12.0.4, I'll try an update.

Edit: can't reproduce anymore after updating to Next 12.1 so it might be a different issue.

eric-burel commented 2 years ago

With Yalc here is how it look like in _app.js:


/***/ "./.yalc/@vulcanjs/react-ui/dist/index.js":
/*!************************************************!*\
  !*** ./.yalc/@vulcanjs/react-ui/dist/index.js ***!
  \************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\nObject.defineProperty(exports,

It feels like my local linked package has been detected as a local dependency instead of an external => Next seems to rebuild it instead of treating it as a module. During the build, it transforms my ES modules and turns import into require. I feel like you might have the same issue with yarn link as with Yalc

keepeek-rd commented 2 years ago

if it could help ... https://github.com/vercel/next.js/issues/35110