Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find low-hanging fruit to minimize bundle size #684

Closed
helfer opened this issue Sep 20, 2016 · 16 comments
Closed

Find low-hanging fruit to minimize bundle size #684

helfer opened this issue Sep 20, 2016 · 16 comments

Comments

@helfer
Copy link
Contributor

helfer commented Sep 20, 2016

The bundle size keeps growing slowly. It would be good to make an effort at reducing the size during a refactor, by checking the size of external dependencies and seeing what large packages we could replace with something else.

@jaydenseric
Copy link
Contributor

This is a pretty urgent issue; the current versions of apollo-client and react-apollo seem to add 178kb (minified) to a bundle:

screen shot 2016-12-14 at 6 52 02 pm

lodash is a mess here, I know a PR recently got merged, but perhaps more can be done? lodash should be used very sparingly client side.

For some reason graphql-tag is pulled in anyway when I only use the webpack loader. Is that necessary?

Once you add essentials such as react, react-dom, react-router, polyfills etc. along with your own application code you get ~500kb minified.

@stubailo
Copy link
Contributor

@jaydenseric is there an easy way to set up a script that will generate the above image for some set of packages? That would be super helpful.

@stubailo
Copy link
Contributor

Also, I think the gzipped size is the most relevant number, which is only 50kb?

@stubailo
Copy link
Contributor

I think this will get rid of some of the huge things like lodash.countby etc: https://github.com/apollostack/graphql-anywhere/pull/21

We could also probably eliminate the graphql-tag dep when using the webpack loader for queries, but I'm curious to see how much space the actual parsed graphql queries take up. Looks like this diagram doesn't include any queries at all.

Thanks for reopening this conversation - I find this topic really useful but we currently don't have good enough tools set up to keep track of the size situation, and would really appreciate your help on that.

@jaydenseric
Copy link
Contributor

th0r/webpack-bundle-analyzer is pretty neat, it serves an interactive webpage that can be zoomed and panned after webpack runs. I haven't fully explored the CLI to work out the most efficient way to add a more permanent analyse script to a project. My webpack config returns an array; for seperate server/client bundles. This chokes webpack-bundle-analyzer for some reason so I have to manually comment out the server config every time I run the script.

@stubailo
Copy link
Contributor

If you did figure it out a PR to this repository would be super appreciated.

@jaydenseric
Copy link
Contributor

Oh, and keep in mind that those pictures, I think, are post webpack v2 tree shaking and uglify dead code elimination. If users don't have both setup it could be different.

Perhaps in this repo we could:

  1. Setup a subdirectory with a webpack config file and a single JS file as an entrypoint, containing import apollo-client from '../'. Tools sometimes treat imports from node_modules differently, so we would need to make sure this import would behave the same for the purposes of analysis.
  2. Add webpack v2 and and webpack-bundle-analyzer as dev dependencies.
  3. Add an analyse script to the package.json that runs the above in production mode.

It would be interesting to be able to see before and after tree shaking / dead code elimination, perhaps it could run a build for 2 different configs and open the analysis in two tabs using different ports.

@stubailo
Copy link
Contributor

To be honest though I doubt there is much a difference with and without tree shaking.

But that strategy seems like a good direction to go. So I just removed all lodash deps from graphql-anywhere, I wonder how much that will help.

@jaydenseric
Copy link
Contributor

jaydenseric commented Dec 14, 2016

Related to tree shaking: #746 (add module entry to package.json).

@stubailo
Copy link
Contributor

I think I just saved 7kb (minified and gzipped - removed lodash.countby and lodash.merge): #1043

jaydenseric added a commit to jaydenseric/apollo-client that referenced this issue Dec 14, 2016
Added a new analyze script to the package.json that makes it possible to inspect what modules make it into the published package and how efficiently it bundles in a webpack v2 project.

The script runs a compilation and builds the analyze test project (that only imports this library) with webpack and the webpack-bundle-analyzer plugin in production mode. Once complete the plugin opens  your browser to an interactive analysis at http://localhost:8888.

See discussion: apollographql#684 (comment).
@stubailo
Copy link
Contributor

BTW, we removed lodash for a lot more savings in #1122

@helfer
Copy link
Contributor Author

helfer commented Jan 12, 2017

I think we've taken care of what qualifies as low-hanging fruit for now, so I'll close this issue. 22.7Kb is pretty small, if you ask me!

@helfer helfer closed this as completed Jan 12, 2017
@damusnet
Copy link

Hi, it would be great if this issue could be re-opened regularly. In our current Next.js app's main bundle, the Apollo Client is taking an increasingly large place. Here is a picture worth a thousand words:

image

Out of 178 kbz of shared dependencies in our node_modules, here is a breakdown:

  • apollo-client: 12.38 kbz
  • apollo-link-rest: 8.88 kbz (this one is brand new, so maybe it hasn't been optimized yet)
  • apollo-cache-inmemory: 5.63 kbz
  • react-apollo: 4.58 kbz
  • apollo-utilities: 3.83 kbz
  • apollo-link: 2.53 kbz
  • graphql: 2.19 kbz
  • apollo-link-http: 1.75 kbz
  • apollo-link-persisted-queries: 0.74 kbz

For a total of 42.51 kbz, not including possible shared hoisted dependencies like lodash. We also plan on adding more, like apollo-cache-persist for instance.

We're obviously big fans of the Apollo Client, deeply thankful for the library, and I hope you'll take this as coming from a good place.

(And yes, there is a lot more to say about our breakdown, and moment.js is going out very soon).

@damusnet
Copy link

Edit: I followed up with an issue on apollo-link-rest because it looks like it's duplicating apollo-utilities and apollo-link instead of sharing them with other dependencies.

Likewise apollo-link embarks its own zen-observable even though it is already required by apollo-client and apollo-link-rest.

❯ yarn why zen-observable
yarn why v1.6.0
[1/4] 🤔  Why do we have the module "zen-observable"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "zen-observable@0.7.1"
info Has been hoisted to "zen-observable"
info Reasons this module exists
   - Hoisted from "apollo-client#zen-observable"
   - Hoisted from "apollo-link-rest#apollo-link#zen-observable-ts#zen-observable"
info Disk size without dependencies: "148KB"
info Disk size with unique dependencies: "148KB"
info Disk size with transitive dependencies: "148KB"
info Number of shared dependencies: 0
=> Found "apollo-link#zen-observable@0.6.0"
info This module exists because "apollo-link" depends on it.
info Disk size without dependencies: "104KB"
info Disk size with unique dependencies: "104KB"
info Disk size with transitive dependencies: "104KB"
info Number of shared dependencies: 0
✨  Done in 1.08s.

Is there any plan to move apollo-link and apollo-link-rest inside this monorepo and/or keep dependencies in sync?

@sbrichardson
Copy link

@damusnet

I also noticed that zen-observable is included multiple times, but it's already in my project in addition the below instances, although I see one version below is the typescript version. These are the non gzipped sizes.

screen shot 2018-05-16 at 1 32 24 pm

screen shot 2018-05-16 at 1 32 09 pm

@damusnet
Copy link

Hi @sbrichardson,

Since I commented on that (already closed) issue, I landed a PR with apollo-link-rest to exclude peerDependencies, but I have not started anything to improve the situation with the apollo-client and its multiple packages.

I don't think anyone is going to see this closed issue, and I would recommend opening a new one with your bundle size map chart. Personally, I am currently not working in a project with apollo anymore, and can't pursue this at the moment.

Cheers

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants