Skip to content

Dependency of a .cjs build may not be loaded correctly #35112

@eric-burel

Description

@eric-burel

Verify canary release

  • I verified that the issue exists in Next.js canary release

Provide environment information

$ /code/stateof/stateofjs-next/node_modules/.bin/next info
/bin/sh: 1: pnpm: not found

Operating System:
  Platform: linux
  Arch: x64
  Version: #33~20.04.1-Ubuntu SMP Mon Feb 7 14:25:10 UTC 2022
Binaries:
  Node: 14.18.2
  npm: 6.14.15
  Yarn: 1.22.5
  pnpm: N/A
Relevant packages:
  next: 12.1.1-canary.6
  react: 17.0.2
  react-dom: 17.0.2

Done in 1.15s.

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

I am building a library of components.

  • Package "my-package-tsup" has shared (ESM, IIFE, CJS), client-only (ESM, IIFE) and server-only (CJS, ESM) exports
  • "my-package-tsup/server" (CJS) depends on "my-package-tsup-dependency" (CJS and ESM).
  • So, server entrypoints are using CJS, while I allow shared code to use either CJS or ESM, with an exports field like this:
{
  "name": "my-package-tsup",
  "version": "1.0.0",
  "description": "",
  "main": "./dist/shared/index.js",
  "type": "module",
  "files": [
    "dist/"
  ],
  "exports": {
    ".": {
      "node": "./dist/server/index.cjs",
      "import": "./dist/shared/index.js"
    },
    "./server": "./dist/server/index.cjs", => this is the one that seems problematic.
    "./client": "./dist/client/index.js"
  },

So, when importing "my-package-tsup/server", Next will correctly load the "dist/server/index.cjs" file. But when this CJS file require it's subdependency, using a require call, it will try to pick the .js ESM export instead of sticking to the .cjs CJS export.

Here is the package.json of the dependency:

{
  "name": "my-package-tsup-dependency",
  "version": "1.0.0",
  "description": "",
  "main": "./dist/shared/index.js",
  "type": "module",
  "files": [
    "dist/"
  ],
  "exports": {
    ".": {
      "node": "./dist/server/index.cjs", => this is the one that should be preferred but instead Next.js complains about trying to require an ESM module. It might be tricked by the "type":"module" and not respect the exports for dependencies, while it works ok for top-level packages
      "import": "./dist/shared/index.js"
    },
    "./server": "./dist/server/index.cjs",
    "./client": "./dist/client/index.js"
  },

To rephrase this:
If a CJS top level package requires one if it's dependency, the exports field of the dependency does not seem to be respected. The ESM export will be loaded, instead of the CJS export.

Expected Behavior

CommonJS dependencies should also use the CommonJS export of their own subdependencies.

To Reproduce

It's not the easiest to reproduce:

git clone 
git checkout feature/datatable
yarn && yarn run build && yarn run publish:local

It will rely on Yalc, so to test you'll need to set it up in a Next app.
Then import @vulcanjs/graphql/server in your Next app and you'll end up with the dreaded https://nextjs.org/docs/messages/import-esm-externals error

Clone, install, and open the "with-tsup" page http://localhost:3000/with-tsup

I seem to be able to have this message: Module not found: Package path . is not exported from package /code/npm-the-right-way/demo-next-app/node_modules/my-package-tsup-dependency (see exports field in /code/npm-the-right-way/demo-next-app/node_modules/my-package-tsup-dependency/package.json).

It's different from the error I have in the other package but could be related, as if "exports" were not understood correctly.

This issue might related: #34956

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIssue was opened via the bug report template.lockedstaleThe issue has not seen recent activity.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions