plugins icon indicating copy to clipboard operation
plugins copied to clipboard

@rollup/plugin-typescript does not resolve modules that use conditional exports when moduleResolution is set to node16

Open apottere opened this issue 3 years ago • 7 comments
trafficstars

  • Rollup Plugin Name: typescript
  • Rollup Plugin Version: 8.3.3
  • Rollup Version: 2.77.0
  • Operating System (or Browser): MacOS 12.4 (21F79)
  • Node Version: 16.14.0
  • Link to reproduction (⚠️ read below): https://github.com/apottere/rollup-typescript-reproduction

Expected Behavior

Both tsc and rollup -c successfully find typescript declarations.

Actual Behavior

tsc compiles successfully, but rollup -c does not - it fails to find the type declarations for the dependency dependency.

Additional Information

The package.json in the included dependency uses Conditional Exports to specify the location of type declaration files for the module: https://github.com/apottere/rollup-typescript-reproduction/blob/main/dependency/package.json#L4-L10

In the main package, tsconfig.compilerOptions.moduleResolution is set to node16: https://github.com/apottere/rollup-typescript-reproduction/blob/main/tsconfig.json#L9

This is correct AFAICT according to the Typescript 4.7 release notes, and tsc can find the declarations and compile the script just fine. For some reason rollup -c cannot, and throws the following error:

[!] (plugin typescript) Error: @rollup/plugin-typescript TS2307: Cannot find module 'dependency' or its corresponding type declarations.
src/index.ts (1:19)

I did a little digging in the module resolution code in the rollup plugin, and it seems like adding "main": "./build/types/", to the dependency's package.json allows rollup to successfully build the bundle, but that's obviously not a great solution. I wasn't able to figure out anything more than that though.

apottere avatar Jul 20 '22 21:07 apottere

Note that this could be caused by @rollup/plugin-node-resolve as well.

apottere avatar Jul 20 '22 21:07 apottere

I don't think this problem is related to conditional exports. If I change the package.json in the provided demo to contain the following exports property, I get the same error:

      "exports": {
          ".": "./build/esm/index.js"
      }

I'm experiencing a similar (or the same?) problem in my project. tsc compiles, but rollup -c does not.

I've added some console logs to createModuleResolver (in 'node_modules/@rollup/plugin-typescript/dist/index.js', see below) and the module in question always resolves to undefined, of course. This leads me to believe that the problem is in @rollup/plugin-typescript, not @rollup/plugin-node-resolve.

It seems to finds the package.json, but does not seem to be able to use the information to resolve the location of the type information. I've tried with [email protected].

 69 function createModuleResolver(ts, host) {
 70     const compilerOptions = host.getCompilationSettings();
 71     const cache = ts.createModuleResolutionCache(process.cwd(), host.getCanonicalFileName, compilerOptions);
 72     const moduleHost = Object.assign(Object.assign({}, ts.sys), host);
 73     return (moduleName, containingFile) => {
 74         const resolved = ts.nodeModuleNameResolver(moduleName, containingFile, compilerOptions, moduleHost, cache);
 75         if (moduleName.startsWith('dependency')) {
 76             console.log({moduleName, containingFile, resolved});
 77         }
 78         return resolved.resolvedModule;
 79     };
 80 }

oxc avatar Aug 27 '22 21:08 oxc

That's definitely the same issue - the exports field in package.json is what defines conditional exports

apottere avatar Aug 28 '22 01:08 apottere

Ah, my bad, I thought it's only called Conditional Exports when it contains different exports for import/require.

oxc avatar Aug 28 '22 07:08 oxc

Typescript also exports a function resolveModuleName. It has the same signature* as nodeModuleNameResolver. However, it only delegates to this function if moduleResolution is set to NodeJs. For Node16, NodeNext and Classic, it delegates to the respective resolver functions.

If I replace ts.nodeModuleNameResolver(...) with ts.resolveModuleName(...), my project compiles as expected.

This function seems to exist for years, and definitely exists in the currently required version v4.2.2.


(*resolveModuleName takes an extra argument resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext. For rollup, I suppose it would make sense to set this to ESNext.)

oxc avatar Aug 29 '22 20:08 oxc

And here seems to be a PR that fixes this: https://github.com/rollup/plugins/pull/1194 :)

oxc avatar Aug 29 '22 20:08 oxc

With v8.5.0 this now works for me, but only if I set the tsconfig module property to NodeNext.

oxc avatar Sep 09 '22 15:09 oxc

Hey folks. This issue hasn't received any traction for 60 days, so we're going to close this for housekeeping. If this is still an ongoing issue, please do consider contributing a Pull Request to resolve it. Further discussion is always welcome even with the issue closed. If anything actionable is posted in the comments, we'll consider reopening it.

stale[bot] avatar Nov 22 '22 20:11 stale[bot]