Apollo-client: Bundle size is very big

Created on 8 Dec 2018  路  6Comments  路  Source: apollographql/apollo-client

I find that Apollos bundle size is quite big, to the point where I'm thinking about moving away from it. Maybe there are things to do about that?

As of right now, Apollo outweighs both React and Material-UI by quite a bit and is therefore my largest dependency. The biggest modules caused by my Apollo usage are:

Total parsed: 137.26 kB
Total GZipped: 39.12 kB

Parsed Sizs:
  apollo-client 38.76 kB
  apollo-cache-inmemory 26.18 kB
  react-apollo 22.48 kB
  subscriptions-transport-ws 12.54 kB
  graphql 10.12 kB
  apollo-utilities 10.07 kB
  zen-observable 6.56 kB
  apollo-link-http 4.94 kB
  apollo-link 2.92 kB
  eventemitter3 2.69 kB

GZipped Sizes:
  apollo-client 10.11 kB
  apollo-cache-inmemory 7.24 kB
  react-apollo 5.88 kB
  subscriptions-transport-ws 3.81 kB
  graphql 2.95 kB
  apollo-utilities 2.93 kB
  apollo-link-http 2.07 kB
  zen-observable 2 kB
  apollo-link 1.13 kB
  eventemitter3 1 kB

I open this issue as a discussion starter

Most helpful comment

@Pajn After using Apollo Client and react-apollo for long time I took a step back and thought critically about how a GraphQL client could be architected from the ground up for efficiency; the result being graphql-react. It's bundle-impact is ~2.5kb (tested here), compared to Apollo's ~40kb.

It's a lot easier to configure and use (one package, less config, uploads work out of the box, etc.), has a way smaller surface area for bugs (zero known ATM), and can even do some things that Apollo can't that matter to me (i.e. SSR errors, easily refresh cache post mutations without also blowing away the mutation payload, etc.) trading off a few things that I don't really need, like subscriptions, which could be implemented in the future anyway.

enamor.app uses graphql-react and Next.js. The JS for fresh app/page load is only ~100kb (including Google Analytics), with subsequent routes around ~5kb each:

screen shot 2018-12-13 at 11 50 15 pm

It might be up your alley.

While some of Apollo's ~40kb bundle impact could be reduced to perhaps ~20kb with polish, I doubt sub 10kb is possible without rethinking the way it works (i.e. scrapping normalized cache, links, gql tagged template strings, graphql dependency, etc.).

All 6 comments

The biggest dependency seems to be the graphql one, which is only used for some typechecks in graphql-tag when i check my peer dependencies.

Also since apollo-utilities is included everywhere in dependencies it is redundantly included in bundle, it should be a peer-dependency to avoid this being added in 4-5 different bundles.

An easy optimization for react-apollo would be to remove prop-types from dependencies and to write your own version of the lodash packages you're using since they dramatically increase bundle-size. Also 麓fbjs麓 is only used for shallowEqual which in essence is also only a few lines of code.

If graphql just is used for validations, could I have to option to disable those in prod? That certainly sounds like low hanging fruit.

The rest though I wouldn't say are that big of a deal. I don't have any duplicate of apollo-utilities in my build and since https://github.com/apollographql/react-apollo/pull/2332 lodash isn't getting pulled in either.
The pulled in part of fbjs is just 405 B parsed and prop-types is 704 B, both around 60% of that GZipped. Sure getting rid of those is a plus but my mind is more thinking about:

Why do I have to pull in zen-observable that with unique transitive dependencies is 10 kB parsed, when I and probably most react-apollo users doesn't even use the API it's enabling.
One idea would be to create apollo-client/lite which does not have watchQuery or subscribe (or only simple callback versions). react-apollo would only depend on this lite version. The export from apollo-client would extend the lite version and add back watchQuery and subscribe maintaining backward compatibility and full ergonomics for plain apollo-client users.

Why does react-apollo have to be 22 kB when react-apollo-hooks is just 10% of that. Sure, it's a lot more polished, provides more APIs and probably have much better validations. But does it really need to be 10x bigger in prod, after uglify? Maybe some of it can be enabled only in dev?

apollo-client seems very big. With cache broken out in apollo-cache-inmemory, network in apollo-link-*, observables in zen-observable and graphql stuff in graphql and apollo-utilities it feels, for an ignorant external user, that it's just stringing things together. Sure there is a lot more to it than that, but still?

Would it be possible to code split and lazy load parts of Apollo, I don't need mutations and subscriptions for the initial point for example?

Just to make it very clear as it's hard to get the correct tone across over the internet with strangers and plain text, I'm not complaining, trying to #perfshame or anything like that.

@Pajn After using Apollo Client and react-apollo for long time I took a step back and thought critically about how a GraphQL client could be architected from the ground up for efficiency; the result being graphql-react. It's bundle-impact is ~2.5kb (tested here), compared to Apollo's ~40kb.

It's a lot easier to configure and use (one package, less config, uploads work out of the box, etc.), has a way smaller surface area for bugs (zero known ATM), and can even do some things that Apollo can't that matter to me (i.e. SSR errors, easily refresh cache post mutations without also blowing away the mutation payload, etc.) trading off a few things that I don't really need, like subscriptions, which could be implemented in the future anyway.

enamor.app uses graphql-react and Next.js. The JS for fresh app/page load is only ~100kb (including Google Analytics), with subsequent routes around ~5kb each:

screen shot 2018-12-13 at 11 50 15 pm

It might be up your alley.

While some of Apollo's ~40kb bundle impact could be reduced to perhaps ~20kb with polish, I doubt sub 10kb is possible without rethinking the way it works (i.e. scrapping normalized cache, links, gql tagged template strings, graphql dependency, etc.).

While some of Apollo's ~40kb bundle impact could be reduced to perhaps ~20kb with polish, I doubt sub 10kb is possible without rethinking the way it works (i.e. scrapping normalized cache, links, gql tagged template strings, graphql dependency, etc.).

Challenge accepted @jaydenseric 馃檪. Seriously though, bundle size reduction is one of the items that's next up on our todo list.

@hwillson and @benjamn - I spent a day doing some rework on the build process with a bunch of improvements. While it does not address the specifics of bundle size, I do think it is worth mentioning here as I have done a ton of housekeeping in preparation for further improvements in ts for tests and added the esm bundle. If you guys can get me feedback I can try to finish this up Wednesday (or after you get time from the holiday). Thanks #4261

We've made a lot of progress on this with AC3 (@apollo/client), and are continuously thinking about bundle size reduction, so I'll close this issue off (but rest assured, bundle size plays into every Apollo Client development decision we make). Thanks!

Was this page helpful?
0 / 5 - 0 ratings