grats icon indicating copy to clipboard operation
grats copied to clipboard

[WIP] Explore persisting queries

Open captbaritone opened this issue 1 year ago • 1 comments
trafficstars

In browser environments or edge computing environments, it would be desirable to make GraphQL execution more light-weight:

  1. Only load resolver code for the fields that your current bundle can actually execute
  2. Perform SDL or query text parsing at runtime
  3. Don't download code for SDL or query text parsing
  4. Don't interpret the query during execution, instead have pre-built code that evaluates the query as a single function

This PR is the start of an exploration in that direction. By piggy-backing on existing persisted query semantics, we can expose a command that will generate a TypeScript module from query text. For now it simply imports the full query, and inlines a pre-parsed query AST (instead of query text).

Currently it does not provide much (if any) value, since I believe that graphql-js is not written in such a way that the unused pieces of code (parser, validator, etc) are removed from the bundle if not used. However, this PR will help us start to explore those idea.

Bundle Size

I've found I can measure the bundle size using esbuild:

➜  yoga git:(persist) ✗ npx esbuild persisted/MyQuery.ts --bundle --outfile=out.js --tree-shaking=true

  out.js  165.5kb

⚡ Done in 12ms

Interestingly switching to more scoped imports makes the bundle size worse! Either way, it looks like some amount of tree-shaking is working.

  • 165.5kb: Baseline
  • 7.2kb: No graphql imports at all, only product code (lower limit)
  • 161.9kb: No schema graphql imports (still large!)
  • 76.2kb No import of execute (significant savings here)
  • 119.5kb (48.8kb minified): Hacking assertSchema out of execute (not possible without hack)
  • 311.5kb Replace pre-parsed query AST with direct call to graphql (which parses and then executes). This shows us how much size we are saving by parsing at persist time.

Note: Sizes are not minified, but our goal here is to understand where the "meat" of the weight it, so that's okay for this phase. To test minified size, pass esbuild --minify.

captbaritone avatar Jan 03 '24 04:01 captbaritone

Deploy Preview for grats failed.

Name Link
Latest commit b9fad47cb5ff08f1c4c480f40cbf547874b1195b
Latest deploy log https://app.netlify.com/sites/grats/deploys/65c16a9df251e70009f7f567

netlify[bot] avatar Jan 03 '24 04:01 netlify[bot]