ApolloClient is not a constructor (apollo-client with nodejs)
For people who like me using Node require
and just want to get it working.
Packages:
npm install graphql apollo-client apollo-cache-inmemory apollo-link-http node-fetch --save
Codes:
const fetch = require('node-fetch')
const { createHttpLink } = require('apollo-link-http')
const { InMemoryCache } = require('apollo-cache-inmemory')
const { ApolloClient } = require('apollo-client')
const gql = require('graphql-tag')
const httpLink = createHttpLink({
uri: 'https://api.github.com/graphql',
fetch: fetch
})
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
})
const query = gql`
query {
viewer {
login
}
}
`
client.query({
query
}).catch((error) => {
console.log(error)
done()
})
The response is error as you need to add Authorization: bearer YOURTOKEN
to request header but that's another thing.
Thanks to this answer
If you're using require
, you can import it like this:
const ApolloClient = require('apollo-client').default
or like this
const { ApolloClient } = require('apollo-client')
Otherwise, you're importing the entire module, which itself is not a constructor.
I have a related issue, although using node --experimental-modules
, not CommonJS. I'm using apollo-client
version 2.6.x
and node version 12.x
so this might change.
Here's how I tried to import it:
import { default as ApolloClient } from 'apollo-client';
const client = new ApolloClient();
The reason why it doesn't work is that --experimental-modules
still imports CommonJS version of a given module even though package.json
has a "module"
field pointing to ESM entry point. It happens because EcmaScript Modules support in Node 12+ relies on either "type"
field in package.json
or "Michael Jackson script" (.mjs
) file extension. And using named import with CommonJS is not supported: https://nodejs.org/api/esm.html#esm_compatibility_with_commonjs_only_versions_of_node_js
So, how to fix? There are two approaches:
- Ask apollo client authors to publish ESM package with
"type": "module"
field inpackage.json
- Use workarounds in the source code
- Use
esm
Here's a workaround:
import apolloClient from 'apollo-client';
const { ApolloClient } = apolloClient;
Bonus: full example
import nodeFetch from 'node-fetch';
global.fetch = nodeFetch;
import apolloClient from 'apollo-client';
const { ApolloClient } = apolloClient;
import apolloInMemoryCache from 'apollo-cache-inmemory';
const { InMemoryCache } = apolloInMemoryCache;
import apolloHttpLink from 'apollo-link-http';
const { HttpLink } = apolloHttpLink;
const cache = new InMemoryCache();
const link = new HttpLink({
uri
});
const client = new ApolloClient({
cache,
link
});
That's not very nice. So there are two paths from here:
- Switch from experimental modules to
esm
loading mechanism which doesn't encourage ecosystem to switch to native node ESM from CommonJS. - Create an pull request in Apollo repo and all its dependencies to put
"type": "module"
and put esm entry point to"main"
in thepackage.json
as a breaking change. Work with maintainers to support temporary compatibility and migration paths. Fork modules and maintain ESM native versions in the meanwhile.