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
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:
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!
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 beinggraphql-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: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.).