Type-safe and simple GraphQL library for ReasonML


#1

I’ve created a type-safe and simple GraphQL library for ReasonML.

Here’s the link: https://github.com/sainthkh/reasonql.

Some of you might be thinking why we need another GraphQL client while we have awesome graphql_ppx and reason-apollo.

There are several reasons but the major one is that graphql_ppx defines the result in Js.t() type. Because of that, we cannot take full advantage of pattern matching, spread syntax, nicer error messages.

reasonql compiler directly translates result into reasonml records and you can get all those benefits.

If you want to learn more about how to use it, please check the link above.


#2

That does look really nice, and I like the record-by-default approach. But my impression is that the alternatives are more established. Can you say more about where this shines, and where the other approaches are superior?


#3

TL;DR;

  • Good: smaller bundle size, record-by-default, blending well with ReasonReact convention. Freedom to define your own cache.
  • Bad: no native support. Sometimes, you might miss out-of-box cache.

Long Answer

Currently, we have 3 options to use GraphQL in ReasonML. (If there are others, please tell me.)

As I said in Why I started this project document, I made ReasonQL because Apollo and Reason Apollo have some problems.

  • To use graphql_ppx and records, you need to write down types manually. Actually, we’ve written them down in GraphQL. We’re doing same things twice, so it can cause errors.
  • reason-apollo doesn’t follow reason react conventions. For example, to use side effects, reason react uses self.send function and reducer. But reason-apollo follows react-apollo convention and make us use Mutation component and onComplete property. I thought mutations should be promisified functions so that we can call them inside reducers.
  • Apollo Client is unforgivably big. apollo family takes about 25~30kb gzipped (Yes, it’s the size after compressed. Before that, they take almost 100kb.) They’re trying to reduce the bundle size. But it seems that it’s a hard battle.
  • And cache is more of a probleme than convenience in my opinion. As a proof, you can see the list of cache related issues here. And some of them started in 2016 and is still not solved yet. I guess the root of this problem is that there is no general cache structure and policy for every app under the sun. Every app is different and they should define their own. It’s harsh but no one can do that for you.

So, I made the ReasonQL the opposite of reason-apollo.

  • Generate record types automatically and decode the fetched data to record - Then, we can do more granular pattern matching, get better error messages and use spread operator.
  • Simple API - Let’s make API simple so that users don’t need to remember much and it doesn’t take much space. (Unfortunately, decoders and encoders take a little bit of space.)
  • Smaller decoder/encoder size - When you open bs.js file and read the code generated by graphql_ppx. They’re huge. I tried to make codec simple.
  • And no default cache system.

And one problem I know with ReasonQL is that it cannot be used in native projects. Sometimes, your project works well with Apollo Client cache. Then, you might miss it.


#4

That sounds really good! Thank you for the detailed writeup. I am on board with the philosophy. In my opinion not being a binding to a JS library is a selling point in itself. However, it does seem like much of your source code is JS instead of Reason, making it more tedious to contribute to. Why is that?


#5

This is probably the main graphql server for ocaml


#6

ReasonQL is a GraphQL client.


#7

I thought about that, too. But 2 things made me implement this in JavaScript.

First of all, I had to bind this AST tree types into ReasonML to use it in my code.

Maybe, it might be my laziness. But I was a bit overwhelmed with them.

Secondly, as “gql({|([\s\S]*)|})” is perfectly fine regular expression, but Reason compiler showed me warnings because there is \ in front of characters like (, {, [.

Maybe, I had to find ways to suppress the warning.

From many people in ReasonML discord server, many people told me about the idea of implementing compiler with ReasonML. If I give up some compile speed, I don’t think that’s impossible. So, I’m experimenting that idea now. Maybe, when ppx is done, it might be easier for you to participate.


#8

Ah sorry I read the post too quickly on my mobile.