apollo-client icon indicating copy to clipboard operation
apollo-client copied to clipboard

Typescript compilation error in Node context

Open chadxz opened this issue 1 year ago • 9 comments

Issue Description

Trying to upgrade from 3.4.17 to latest and have started running into this error as of 3.5.0:

index.ts:5:8 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("@apollo/client")' call instead.
  To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field `"type": "module"` to '/project/workspace/package.json'.

5 } from "@apollo/client";
         ~~~~~~~~~~~~~~~~

I have included a reproduction link. Simply using "module": "NodeNext" in tsconfig.json will cause this. This is the recommended setting for "modern Node.js projects" per the TypeScript documentation. Do you have any recommendations on how to address this? My project is not ESM today.

Link to Reproduction

https://codesandbox.io/p/devbox/recursing-yalow-s8fmpr

Reproduction Steps

Run tsc in the terminal of the repro. Main config setting to set is "module": "NodeNext" in tsconfig.json

@apollo/client version

3.10.4

chadxz avatar Jun 13 '24 14:06 chadxz

Hey @chadxz 👋

Thanks for opening this! I'll do my best to take a look at this today. I'm currently working on a reproduction for a potential React bug and I'm on vacation starting tomorrow for the next week. If not me, I'll see if one of the other maintainers has some bandwidth to take a look. Thanks!

jerelmiller avatar Jun 13 '24 17:06 jerelmiller

Thanks for your patience!

There are two things that look like would get this to work for you. Either you'll need to specify your app with type: "module" in package.json so that you aren't using CommonJS, or you'll need to update your import to ensure you'll getting the CommonJS build. You can do this using the main.cjs path.

import {
  ApolloClient,
  InMemoryCache,
  type NormalizedCacheObject,
} from "@apollo/client/main.cjs";

While this is less than ideal, this should get you what you need for now. We'll be adding proper ESM support in v4 to avoid this issue going forward. Hope this helps!

jerelmiller avatar Jul 08 '24 16:07 jerelmiller

Thanks for the suggestion @jerelmiller!

I tried this and it looks like that is incompatible with TypeScript as well, unless I'm still missing something:

Screenshot 2024-07-08 at 2 44 18 PM

This is using @apollo/[email protected]

The same is true on the reproduction link:

Screenshot 2024-07-08 at 2 48 47 PM

chadxz avatar Jul 08 '24 19:07 chadxz

@chadxz thats...odd. I used your original reproduction and forked it to check. Here is my fork: https://codesandbox.io/p/devbox/gifted-thompson-y875p2?file=%2Findex.ts%3A4%2C8

If you run npx tsc or yarn tsc (pick your favorite) in the terminal, it passes just fine.

Without /main.cjs:

Screenshot 2024-07-08 at 2 10 19 PM

With /main.cjs Screenshot 2024-07-08 at 2 12 06 PM

Odd that you're still seeing that error in the reproduction 🤔

jerelmiller avatar Jul 08 '24 20:07 jerelmiller

If you hover over the 3 dots at the beginning of the package name in your screenshot you'll probably see the same message I am seeing.

I can confirm that compiling works fine in the reproduction, but I think that's because it has a minimal tsconfig.json. If you add "strict": true to the tsconfig.json it will spit out the error at compile time.

chadxz avatar Jul 08 '24 20:07 chadxz

Also facing this issue, is there any progress?

Adding the .d.ts file for @apollo/core/main.cjs gets rid of TS's complaints, but doesn't feel quite right that it's necessary to do this...

To confirm, this is with module: 'Node16', moduleResolution: 'Node16', strict: true in the tsconfig, where I'm building a library that exposes some logging functionality for consumers, which makes use of the ApolloLink from @apollo/client

je00037 avatar Aug 21 '24 15:08 je00037

+1.

I also have this issue with Node16.

ashleyww93 avatar Sep 02 '24 21:09 ashleyww93

Same issue with NodeNext

+1

aorsten avatar Sep 06 '24 12:09 aorsten

you can add your own package.json "type": "module"

xenonhammer avatar Oct 14 '24 11:10 xenonhammer

I just ran into this. Best I can tell, this is because in the package.json, the types point to the ESM types, and so typescript thinks its importing esm instead of cjs. This was fixed in the server package here, by explicitly shipping cjs types: https://github.com/apollographql/apollo-server/pull/7614

HiranmayaGundu avatar Nov 22 '24 03:11 HiranmayaGundu

I just run into this. Please fix the types, they are simply wrong. As @HiranmayaGundu correctly said, cjs types are wrong. Consider this tool for more information.

you can add your own package.json "type": "module"

This is not an option for some users. I don't know if asking the user to migrate their whole codebase to ESM is an acceptable workaround. Fixing types should be a matter of emitting CJS types as well.

notaphplover avatar Feb 06 '25 11:02 notaphplover

@notaphplover we are in fact shipping .d.cts files for quite a while now - but it seems we are missing the .d.cts file for main.cjs for some reason.

We'll look into this, but in the meantime it should be possible for you to import from "@apollo/client/core/core.cjs" etc. instead of the main entry point.

phryneas avatar Feb 06 '25 11:02 phryneas

@notaphplover The main.d.cts file has been fixed and is now shipping starting with 3.12.11. Hope this helps 🙂

jerelmiller avatar Feb 07 '25 17:02 jerelmiller

I updated to 3.12.11. I am able to get my app to properly typecheck by changing all my from "@apollo/client" to from "@apollo/client/main.cjs" (and similar for from "@apollo/client/link/retry"). I also needed to update places where I was referring to GraphQLError to instead be GraphQLFormattedError coming out of the client.

I'm not thrilled about having to do this deep import. I don't have to do this with other libraries, and when I do finally get around to migrating my codebase to ESM, it's going to require yet another find/replace to fix this.

At least I can upgrade now. Thanks!

chadxz avatar Feb 07 '25 20:02 chadxz

I'm not thrilled about having to do this deep import

We hear you. We will be doing a proper implementation for ESM in 4.0 with support for the exports field among others. I believe we'll still continue to ship CJS as well, but the package should be better setup to handle the more modern tooling.

Glad to hear you can at least upgrade! Thanks for confirming.

jerelmiller avatar Feb 07 '25 21:02 jerelmiller

@notaphplover The main.d.cts file has been fixed and is now shipping starting with 3.12.11. Hope this helps 🙂

It seems not fixed in 3.12.11

aramis-it avatar Feb 10 '25 07:02 aramis-it

@aramis-it at this point we're going to need a specific example of what you are doing that's not working for you.

phryneas avatar Feb 10 '25 09:02 phryneas

Hey @phryneas, I can recreate the issue as well, just write an import in a typescript file and try to compile it targeting commonjs:

import { ApolloClient, InMemoryCache } from "@apollo/client"

export const apolloClient: ApolloClient<unknown> = new ApolloClient({
	cache: new InMemoryCache(),
	uri: "https://super-duper-graphql-api",
})

The following error should be displayed:

error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("@apollo/client")' call instead.
  To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field `"type": "module"`

After having a look at the type definitions:

@apollo/client/main.d.cts

export * from "./index.d.ts";

This is wrong. CJS type definitions are different than ESM type definitions the same way CJS modules are different than ESM modules. In order to fix this, you need to compile CJS types instead of exporting ESM ones.

notaphplover avatar Feb 10 '25 11:02 notaphplover

import { ApolloClient, InMemoryCache } from "@apollo/client"

export const apolloClient: ApolloClient = new ApolloClient({ cache: new InMemoryCache(), uri: "https://super-duper-graphql-api", })

Yes, as previously written in this issue, if you are using CommonJS at this point while relying on Node16 module resolution (and with a bunch of specific bundler configurations), you need to import a real file with a file extension instead of the package name:

-import { ApolloClient, InMemoryCache } from "@apollo/client"
+import { ApolloClient, InMemoryCache } from "@apollo/client/main.cjs"

export const apolloClient: ApolloClient<unknown> = new ApolloClient({
	cache: new InMemoryCache(),
	uri: "https://super-duper-graphql-api",
})

With 3.12.11, we fixed a bug where other .d.cts were present, but the main.d.cts file was missing.

We get that this is inconvenient, and we will fix that in the next major release, but we cannot change that during the 3.x release as it is a breaking change.

This is wrong. CJS type definitions are different than ESM type definitions the same way CJS modules are different than ESM modules. In order to fix this, you need to compile CJS types instead of exporting ESM ones.

This were true if we were using default exports, but we are not using default exports anywhere in the library. For the artifacts we create, this should be sufficient.

phryneas avatar Feb 10 '25 12:02 phryneas

Named export 'useQuery' not found. The requested module '@apollo/client' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using:

node 22, reactjs 19, vite 5.4, typescript 5.7.3

tsconfig:

"target": "ES2022",
"module": "ES2022",
"moduleResolution": "bundler",

aramis-it avatar Feb 11 '25 06:02 aramis-it

@aramis-it that is a different problem - in your case, please import from @apollo/client/index.js instead of @apollo/client. If that should not solve the problem, please open a new issue so that we can track it separately.

phryneas avatar Feb 11 '25 08:02 phryneas

This will be solved in Apollo Client 4.0.

It might still take a while until we're ready to ship (we just released the first alpha, please go over the changelog and try it out!), but the code for this change has already been merged, so I'm going to close this issue.

phryneas avatar Mar 14 '25 12:03 phryneas

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.

github-actions[bot] avatar Mar 14 '25 12:03 github-actions[bot]

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. For general questions, we recommend using our Community Forum or Stack Overflow.

github-actions[bot] avatar Apr 14 '25 00:04 github-actions[bot]