apollo-client: @apollo/client v3 broken in Rollup & Snowpack

Tracked it back to this item:

https://github.com/apollographql/apollo-client/blob/master/src/react/react.ts#L8

The require function doesn’t exist inside an ES Module (any file with import or export syntax), which is causing the package to fail in some bundlers.

Happy to help brainstorm ideas on how to solve if you’d like, but would strongly recommend against shipping 3.0 with broken support in any major bundlers.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 16 (8 by maintainers)

Commits related to this issue

Most upvoted comments

Also about ES Modules related, @apollo/client still uses three dependencies exported as CommonJS:

I have noticed this trying to make @apollo/client work directly in the browser, without using any build/bundled process during development.

Yup, 100% agreed and wish this was better supported in ESM. But even Webpack is limited by how much it can statically analyze. Bundlers can see that @apollo/client is importing & requiring React, but they can’t tell at build-time wether that runtime function that does it will or won’t ever be run, so a bundler will normally just bundle “react” into your app just to be safe.

Based on the above, I’m 99% sure that Webpack is bundling "react" into every application that uses @apollo/client v3 regardless of whether the that code path ever gets hit. I don’t think it’s actually buying you that much.

I’d recommend:

  1. Decide that @apollo/client is for React, and remove the layer of indirection / just import react directly. Webpack is already including React anyway, so this isn’t too different from the way it is behaving today, but you’d be able to support Rollup, Snowpack, etc, etc.
  2. Split out anything React-specific from @apollo/client into a new @apollo/react or @apollo/client-react. I’d actually recommend this regardless of this issue, since it would help you scale to @apollo/client-{FRAMEWORK} without much thrash, but that’s just my outsiders opinion.
  3. Move anything React-specific into a @apollo/client/react sub-path within the package, and have users import from there directly. Everyone who npm installs the package will still get react as a dependency, but if the user never imports @apollo/client/react in their project, bundlers should be smart enough to handle that.

@FredKSchott we’ll publish a new beta shortly (I’ll post back here when it’s ready). Thanks!

That worked! Thanks again

Thanks all - sorry, I misinterpreted the original problem regarding the example app I shared (I was focused on the use case of not needing React).

We had discussed a lot of the ideas in this thread back when we decided to integrate our React hooks into the @apollo/client core. The thing is, we’re very focused on providing an as easy to use out of the box Apollo Client + React experience as possible. React is the only view layer we officially support ourselves, which means it gets higher priority in our design decisions and usability goals. We’ll put some more thought into this, but the most likely outcome here (for the short term) is that we’ll just remove the lazy load / require for the AC 3.0 release. We’ll then investigate a way to make React more detachable, but that method will not be part of the default out of the box @apollo/client package install experience. TBD though, more details shortly.

  1. Split out anything React-specific from @apollo/client into a new @apollo/react or @apollo/client-react. I’d actually recommend this regardless of this issue, since it would help you scale to @apollo/client-{FRAMEWORK} without much thrash, but that’s just my outsiders opinion.

I really like the second option from @FredKSchott!

@hwillson FWIW, the example you are citing is no-react, where the lazy require is not even needed.

I did a workaround though to make it work with Rollup/React:

I created a rollup plugin which replaces the lazy require with a static import.

export function patchApolloReactRequire() {
    return {
        name: 'patch-apollo-react-require',
        transform(code, id) {
            if (id.endsWith('@apollo/client/react/react.js')) {
                return `import React from 'react';export function requireReactLazily(){return React}`;
            }
        }
    }
}