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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make typescript imports work with nodenext module resolution #50357

Open
wants to merge 1 commit into
base: canary
Choose a base branch
from

Conversation

lucgagan
Copy link
Contributor

@lucgagan
Copy link
Contributor Author

Looks like this is failing because it cannot resolve dist/compiled/* paths.

I am not sure how to properly fix this.

"./dist/compiled/*": {
  "require": "./dist/compiled/*"
},

This fails because it cannot find /dist/compiled/chalk

The file we want is ./index.js. However, if we change export to:

"./dist/compiled/*": {
  "require": "./dist/compiled/*/index.js"
},

then other dependencies start to fail:

dist/compiled/arg/index.js/index.js

etc.

Long story short, I tried patching them one by one...

"exports": {
  ".": {
    "import": "./index.js",
    "types": "./index.d.ts"
  },
  "./amp": {
    "import": "./amp.js",
    "types": "./amp.d.ts"
  },
  "./app": {
    "import": "./app.js",
    "types": "./app.d.ts"
  },
  "./babel": {
    "import": "./babel.js",
    "types": "./babel.d.ts"
  },
  "./cache": {
    "import": "./cache.js",
    "types": "./cache.d.ts"
  },
  "./client": {
    "import": "./client.js",
    "types": "./client.d.ts"
  },
  "./config": {
    "import": "./config.js",
    "types": "./config.d.ts"
  },
  "./dist/compiled/@next/react-refresh-utils/dist/ReactRefreshWebpackPlugin": {
    "require": "./dist/compiled/@next/react-refresh-utils/dist/ReactRefreshWebpackPlugin.js"
  },
  "./package.json": {
    "require": "./package.json"
  },
  "./dist/compiled/@next/react-refresh-utils/dist/runtime": {
    "require": "./dist/compiled/@next/react-refresh-utils/dist/runtime.js"
  },
  "./dist/pages/*": {
    "require": "./dist/pages/*.js"
  },
  "./dist/compiled/devalue": {
    "require": "./dist/compiled/devalue/devalue.umd.js"
  },
  "./dist/compiled/regenerator-runtime": {
    "require": "./dist/compiled/regenerator-runtime/runtime.js"
  },
  "./dist/compiled/unistore": {
    "require": "./dist/compiled/unistore/unistore.js"
  },
  "./dist/next-config-validate.js": {
    "require": "./dist/next-config-validate.js"
  },
  "./dist/compiled/@babel/runtime/package.json": {
    "require": "./dist/compiled/@babel/runtime/package.json"
  },
  "./dist/compiled/webpack/*": {
    "require": "./dist/compiled/webpack/*.js"
  },
  "./dist/compiled/acorn": {
    "require": "./dist/compiled/acorn/acorn.js"
  },
  "./dist/compiled/neo-async": {
    "require": "./dist/compiled/neo-async/async.js"
  },
  "./dist/compiled/webpack/webpack": {
    "require": "./dist/compiled/webpack/webpack.js"
  },
  "./dist/compiled/loader-runner": {
    "require": "./dist/compiled/loader-runner/LoaderRunner.js"
  },
  "./dist/compiled/@edge-runtime/primitives/crypto": {
    "require": "./dist/compiled/@edge-runtime/primitives/crypto.js"
  },
  "./dist/compiled/stacktrace-parser": {
    "require": "./dist/compiled/stacktrace-parser/stack-trace-parser.cjs.js"
  },
  "./dist/compiled/@next/react-dev-overlay/dist/middleware": {
    "require": "./dist/compiled/@next/react-dev-overlay/dist/middleware.js"
  },
  "./dist/compiled/@edge-runtime/primitives/abort-controller": {
    "require": "./dist/compiled/@edge-runtime/primitives/abort-controller.js"
  },
  "./dist/compiled/watchpack": {
    "require": "./dist/compiled/watchpack/watchpack.js"
  },
  "./dist/compiled/arg/index.js": {
    "require": "./dist/compiled/arg/index.js"
  },
  "./dist/compiled/*": {
    "require": "./dist/compiled/*/index.js"
  },
  "./dist/client/components/noop-head": {
    "require": "./dist/client/components/noop-head.js"
  },
  "./dist/shared/lib/*": {
    "require": "./dist/shared/lib/*.js"
  },
  "./dist/compiled/sass-loader": {
    "require": "./dist/compiled/sass-loader/cjs.js"
  },
  "./dist/compiled/punycode": {
    "require": "./dist/compiled/punycode/punycode.js"
  },
  "./dist/compiled/string_decoder": {
    "require": "./dist/compiled/string_decoder/string_decoder.js"
  },
  "./dist/build/webpack/config/blocks/css": {
    "require": "./dist/build/webpack/config/blocks/css/index.js"
  },
  "./font/google/target.css": {
    "require": "./font/google/target.css"
  },
  "./font/local/target.css": {
    "require": "./font/local/target.css"
  },
  "./dist/client/*": {
    "require": "./dist/client/*.js"
  },
  "./dist/compiled/constants-browserify": {
    "require": "./dist/compiled/constants-browserify/constants.json"
  },
  "./dist/compiled/os-browserify": {
    "require": "./dist/compiled/os-browserify/browser.js"
  },
  "./dist/compiled/@next/font/*/loader": {
    "require": "./dist/compiled/@next/font/*/loader.js"
  },
  "./dist/compiled/@next/react-refresh-utils/dist/loader": {
    "require": "./dist/compiled/@next/react-refresh-utils/dist/loader.js"
  },
  "./dist/compiled/assert": {
    "require": "./dist/compiled/assert/assert.js"
  },
  "./dynamic": {
    "require": "./dynamic.js"
  },
  "./document": {
    "import": "./document.js",
    "types": "./document.d.ts"
  },
  "./error": {
    "import": "./error.js",
    "types": "./error.d.ts"
  },
  "./font": {
    "import": "./font/index.js",
    "types": "./font/index.d.ts"
  },
  "./font/google": {
    "import": "./font/google.js",
    "types": "./font/google.d.ts"
  },
  "./font/local": {
    "import": "./font/local.js",
    "types": "./font/local.d.ts"
  },
  "./head": {
    "require": "./head.js",
    "import": "./head.js",
    "types": "./head.d.ts"
  },
  "./headers": {
    "import": "./headers.js",
    "types": "./headers.d.ts"
  },
  "./image": {
    "import": "./image.js",
    "types": "./image.d.ts"
  },
  "./link": {
    "require": "./link.js",
    "types": "./link.d.ts"
  },
  "./navigation": {
    "import": "./navigation.js",
    "types": "./navigation.d.ts"
  },
  "./router": {
    "import": "./router.js",
    "types": "./router.d.ts"
  },
  "./script": {
    "import": "./script.js",
    "types": "./script.d.ts"
  },
  "./server": {
    "import": "./server.js",
    "types": "./server.d.ts"
  },
  "./web-vitals": {
    "import": "./web-vitals.js",
    "types": "./web-vitals.d.ts"
  }
},

Long story short, this approach is not going to work.

Pretty big problem as it makes next.js pretty much unusable with default TypeScript v5 settings.

@lucgagan
Copy link
Contributor Author

Just in case, leaving this PR open to drive attention. Not expecting work to continue, as it seems that this approach will not work. Unless there is some underlying work that can be done with how the loaders function.

@parcelgraph
Copy link

parcelgraph commented Nov 8, 2023

Why so complicated? Something as simple as this should work for the majority of the public API:

  "exports": {
    ".": "./index.js",
    "./*": "./*.js",
    "./font/*": "./font/*/index.js",
    "./dist/*": "./dist/*/index.js"
  },

@llllvvuu
Copy link

llllvvuu commented Feb 1, 2024

Why so complicated? Something as simple as this should work for the majority of the public API:

Unfortunately these wildcards are too aggressive,

  • they will change dist/compiled/arg/index.js to dist/compiled/arg/index.js/index.js
  • they will change next/link.js to next/link.js.js

We can fix these two issues with:

+    "./dist/*.js" : "./dist/*.js",
    "./dist/*" : "./dist/*/index.js",

But we still fail to resolve dist/compiled/devalue to dist/compiled/devalue/devalue.umd.js, dist/compiled/regenerator-runtime to dist/compiled/regenerator-runtime/runtime.js, etc. Now it seems the issue here is that if we use "exports" to resolve one name, we must use it to resolve ALL names. So we can't resolve some names through "exports" and everything else through the default node resolution algorithm.

There are a lot of these packages: find . -name "package.json" -exec jq -r 'if .main != "index.js" then .main else empty end' {} + | less

It looks like "exports" is not expressive enough to handle such vendored packages unfortunately.

@klippx
Copy link

klippx commented May 28, 2024

This wont work, it is not nearly enough to make things work I am afraid. But good for driving discussion. See #46078 (comment)

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

Successfully merging this pull request may close these issues.

[NEXT-779] next/* - Typescript cannot find module when moduleResolution=nodenext and type=module
6 participants