Why GraphQL Does Win? [case study with GitHub API]

This all started from personal wish to try GraphQL, to see how it works, to code something, and then make a decision, based on own experience. I also tend to grasp new technologies, as fast as I can, and that is why this project dedicated to new things, at least some first touch.

TL;DR

GitHub API, REST vs. GraphQL, XmlHttpRequest vs. Fetch API, HTML5 template, ES6 String Literals, ES2017 import/export, ES2017 async/await, URLSearchParams API, Chrome Canary, NodeJS, npm vs. bower, Bootstrap v4.0.0-beta, v4-dev,  Pace progress bar, OAuth vs. Auth0, deployment to Heroku.

I was working on set of work-related tasks and personal sandbox projects, and I came up with task idea:

Get list of GitHub repositories based on my custom data about owner and name.

Later on, my idea reminded me existed web site created by Michael RambeauBestOf.Js.Org (great resource, check it out).

But here, I will share my experience about working directly with GitHub API, with their version 3 (REST-based) and version 4 (GraphQL-based).

So let’s say I have array of objects representing GitHub repository owner and name:

For my test application, I have 20 records. It’s important, because later on I will analyze performance (by number of requests, time and size of data). And I have 3 variants to get those data:

  • GitHub API v3 – REST-based API
  • GitHub API v3 via github-tools/gitgub – github-api wrapper.
  • GitHub API v4 using GraphQL

For educational and testing purpose, I use Fetch API to create request to server.

GitHub API v3 – REST-based API

GitHub API v3 via github-tools/gitgub – github-api wrapper.

After you include GitHub.bundle.min.js in html code, you will have window.GitHub available, and u can code. And this GitHub API wrapper, gives me easier way regarding authentication and existed functions to fetch repository data by owner and name with ability to view details. It’s also good, that this wrapper already knows public URL to API, so no need to provide it explicitly.

In both code snippets above, the flow is next:

  1. I get my custom data and token and later I pass to functions.
  2. Then I provide repo owner and repo name to either my personal code to fetch/GET or “github API wrapper” code.
  3. Then, I render every data on page.

And if we compare both approaches, performance of getting data from server is quite the same. Let’s say I want to render 20 records, so I will send 20 GET requests, and as soon as I fetch it, I show on page. And if u look to structure of response objects, it’s huge – GitHub API returns lot of data.

And here is time for GraphQL to step into. Main goal of GraphQL is simplification of complex requests. You can simply program what requests is going to be, and what you want to receive in response.

GitHub API v4 using GraphQL

It’s not simple example I’ve got for myself. Please research Google for simpler examples. But I had a task, and my goal was to implement it. In fact I didn’t come up with below query at first time – I created post on GitHub Platform Forum, and people helped me to realize, how to do it. Here is IDL file content of GraphQL query:

This content can be executed in GraphQL Explorer, which requires GitHub authentication:

And if in GraphQL Explorer it looks simple, in JavaScript it’s a bit complex:

 

Yes, v3 approach creates dozen of requests (due to v3 design, there is no endpoint to fetch list of repositories), and v4, gives closer ability, and does only 1(2) request(s).

Outcomes

Looking to Chrome Canary v63 Networking tab now, to compare time performance:

  • v3 approach it sends 40 requests (OPTIONS+GET), which takes 1.4/1.6/1.8 sec
  • v4 it sends ONLY one POST request (in fact 1 OPTIONS + 1 POST), which takes ~1.5/1.8/2.0 sec.

Yes, from time perspective, all approaches are quite the same, and even sometimes GraphQL is slower. But interesting observation, that if ONLY one approach works in browser, then I guess requests cashed, and then BOTH approaches take on average ~1.2 sec, which is ok, but complicated to calculate who is better.

Looking to Networking tab, but considering number of server-returned properties:

  • v3 approach in scope of one GET request about repository info gives you 108 unique properties/data fields (which is 20*108 = 2160 properties per one total request), and
  • v4 approach (GraphQL) gives you ability to adjust wanted list of properties from server. In my example one POST request offers in response 21 unique properties, which is multiplied by requested 20 repositories, and in total it’s 20*21 = 420 properties.  And this is great, this is why GraphQL does win…

Looking to Networking tab, but to total size of requests.

  • v3 approach goes via 40 requests (for 20 repos) and it downloads 93 kB.
  • v4 approach goes via 2 requests (for 20 repos) and it downloads 6.1 kB.

 

Other Tech Notes

Modules import/export

First of all – we can use import/export, with no transpilers now. Hooray, finally…  It was available since early Chrome Canary versions, then Chrome v60 (w/ flag), and since Chrome official v61 we can run our pages freely. And since NodeJS v 8.5.0 ES Modules are available also, under files with extension *.mjs.

Twitter Bootstrap v4

I chose Twitter Bootstrap for my trivial UI, not because I know it, or all web community uses it, but to test their recent code changes in v4.0.0-beta,  which I discovered is buggy. I follow their GitHub repo, and I was able to bower install bootstrap#v4-dev directly from dedicated master with fixes to use it locally. But then, Sep-05-2017, they dropped bower support, and next day, when I deleted bower_components, I wasn’t able to install at all. So I did npm install bootstrap#v4-dev, and latest code is able for me to use.  They also preparing to having dedicated bootstrap-js and bootstrap-css. Details here.

 

Fetch API vs. XMLHttpRequest

During work on the task, I experienced an issue, that using Fetch API, browser sends 2 requests to GitHub server: OPTIONS + GET. I’ve read some helpful info here, and later on just tried simple XmlHttpRequest, and request was only one – GET. If I provide any kind of headers to Fetch options, it then goes OPTIONS => GET. If I omit options.headers, then Content-Type is text/plain by default, it it goes only GET request. With GitHub API v4 requests, it goes OPTIONS+POST.

My point is, that they are different, their definition might be similar, but behavior, in some edge cases really differs. In my case, it’s somehow related with CORS and requests from my host (localhost, github-pages or Heroku instance) to public server.

BTW, if I look on Safari to Network tan, v4 approach (GraphQL) downloads 12kB and it takes 0.35-1.50 sec, and Fetch API does it via ONLY ONE POST request.

 

GitHub API

By using simple unauthorized requests it’s limited per day, but using token it works perfect. Saving token to codebase triggers GitHub to revoke that token, that is why u need store token string in environment properties. My first approach, was simple text file, and I fetched it by GET and then pass it though the JavaScript code.

 

Auth0 vs OAuth

I understood, that OAuth looks specific, but at the first glance, it’s very complicated to grasp, how it is different from Auth0, OpenID, SSO, Okta and other similar authentication services. I’ve read documentation from GitHub and other pages, for 2 days, and I did some variant, but I feel, like there is better way, smarter. But assuming it’s first time I worked with OAuth and GitHub API, I think it’s acceptable for me to stop there. I think, when I have one more project rlated with OAuth, I will watch this video one more time.

 

GitHub Apps vs GitHub OAuth Apps

It’s first time, I touched this area, and as all apps, these both are available for being in marketplace. So if there is need to create application, and earn money on it, there is technical ability, but application should meet requirements first before going to market. I did not have such purpose, but was interesting o wok with the technology.

 

NodeJS, ExpressJS, Heroku

It’s so easy to setup NodeJS/ExpressJS project/server using Heroku. I used deployment approach from github repository. So if I push my changes, in a few seconds, it’s deployed, and I ca test my almost full functioning web site.

 

Code

Services

Resources

PS

I also published this article to Medium.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s