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:

  1. Ask apollo client authors to publish ESM package with "type": "module" field in package.json
  2. Use workarounds in the source code
  3. 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:

  1. Switch from experimental modules to esm loading mechanism which doesn't encourage ecosystem to switch to native node ESM from CommonJS.
  2. Create an pull request in Apollo repo and all its dependencies to put "type": "module" and put esm entry point to "main" in the package.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.