How do you use GraphQL with Clojurescript?

1,819 views
Skip to first unread message

Nick Pavlica

unread,
Jun 26, 2017, 2:18:52 PM6/26/17
to ClojureScript
All,
  Like most new Clojure/Clojurescript users, I'm trying to navigate the various library combinations to accomplish my goals.  In this case, I'm trying to find a good set of cljs libraries to build a client app for a GraphQL based server.  My understanding is that Om Next, and Reagent plus Re-frame, are the most popular client library options.  That being said, what's the best way to interact with a GraphQL server?  I'm guessing that you can combine them with a specialized GraphQL client like Apollo, or Relay Modern;  I understand that this may be redundant, but I'm not exactly clear on how you make the most out of GraphQL without a specialized client.  Is it just better to just use cljs with one of these clients and forgo the frame works?  Your guidance is appreciated!

Thanks!
--Nick    

Nick Pavlica

unread,
Jun 30, 2017, 1:40:37 PM6/30/17
to ClojureScript


Ok,
  We are at over 40 views, and it seems like no one in the Clojurescript community is familiar with using GraphQL, or doesn't have the time to give some good pointers.  This is the hard part of newbies trying to adopt technologies that are often much better than the mainstream.  The desire to use best of bread design, currently GraphQL, and best of breed languages is there, but it's a tough sell to learn a language, multiple frameworks, and how to best integrate with a GraphQL client lib. Hopefully this will change, and if I can find the time to wade through the plethora of libraries, and get all the parts working, I'll try to document one way to do it.  The hard part is not going back to the familiar, which is hard not to do :)

Cheers!
--Nick 

 

Luke Burton

unread,
Jun 30, 2017, 4:22:18 PM6/30/17
to clojur...@googlegroups.com


> On Jun 30, 2017, at 10:40 AM, Nick Pavlica <lin...@gmail.com> wrote:
>
> Ok,
> We are at over 40 views, and it seems like no one in the Clojurescript community is familiar with using GraphQL, or doesn't have the time to give some good pointers.

The Clojure community is small and has a different set of values and expectations. I would consider the possibility that you’re framing your question in a way that doesn’t resonate very clearly with people who might have an opinion.

If I understand it correctly, you’re asking “should I query a GraphQL backend directly or via a framework?” Since the cost of experimentation in this language is so low, most people will be thinking “why don’t you just try both approaches?”

If you can’t find a framework that does it, chances are it’s so easy to do in Clojure/ClojureScript that nobody bothers to put an abstraction there. What happens when you make a GraphQL query yourself? If it’s super easy you may elect to forego any frameworks even if they exist!

Another community idiom is that our programs are collections of small, composable functions. When written this way, the cost of making a framework choice that turns out to be suboptimal is very low. In writing Clojure I’m generally much less anxious about upfront framework decisions compared to other languages - I’m willing and able to change quite fundamental components if things aren’t working out. This is another reason questions like “which thing does everyone choose for this?” are often answered with “pick the one that works for you”.

Luke.

Dustin Getz

unread,
Jun 30, 2017, 4:35:40 PM6/30/17
to clojur...@googlegroups.com
It's not clear to me that the cljs community has converged on graphql as a best practice. some people have certainly adopted it but it doesn't feel like there are very many to me. for example, Datomic has been doing what GraphQL offers plus much more since like 2013, it's not clear that graphql adds anything to what cljs users have already been doing since at least as long as facebook is been doing it internally. this isn't what you asked, but could explain the silence.

Nick Pavlica

unread,
Jun 30, 2017, 8:25:00 PM6/30/17
to ClojureScript
Hi Luke,
  Thanks for addressing my question, and helping better understand Clojurescript and the community!

I'm sure my question was unclear, and is certainly poorly constructed for the initiated; sorry about that.  The difficulty, is that for someone new to the Clojure* community, it can be a little overwhelming.  While Clojure* the language is beautifully decomplected, in many ways the lack of apparent focus by the community makes it hard to get started.  For example, there are at-least three runtime implementations, each with their own caveats, and a set of libraries that try to bridge them.  There are two popular build tools, multiple repels, and so on, until you start running in circles trying to figure out what best practice is.   This breadth is certainly great for those that have been here a while, but it seem to takes away from the depth that other small communities like Elixir are developing by focusing their limited resources behind an primary effort like Phoenix. I've seen this play out in other communities like Ruby On Rails , and many others, that eventually grew into what we view as "mainstream".  It's definitely a challenge to come into the Clojure* world from more traditional communities.  The idea of baking a cake without a well vetted and thought through recipe really feels foreign.  I'm sure that in time that uncomfortable uncertainty just goes away.  I almost wonder if more effort should be made by the community to help newbies get over this hurdle.  I'm sure experimentation is quite easy once your used to the Clojure* way, but I think that baggage that we carry with us makes it hard to see.  For example, When Ember was cool, I spent allot of time learning it, then Angular came along and there was another big learning curve.  I think that most people coming to Clojure* would look at trying to learn two frameworks just to experiment with, would wince a little, because it wasn't trivial to switch between other frameworks in the past.  With that said, I wonder if this would better have been a little better form of the question.  It would still highlight my ignorance of the "Clojure Way", but would maybe have been a little more focused:

" All, I'm new to the Clojure* community and would like to build a SPA style web application, and eventually mobile equivalents that needs to work with GraphQL endpoints.  I've seen a number of tools, libraries, and frameworks, but I'm unclear which one has the most community support behind it.  I've noticed that Om, and Reagent plus Reframe are mentioned the most in presentations and blog posts, but there's limited documentation on each their project pages, and neither have reached 1.0.  Ideally, I would like to integrate with the Apollo, or Relay Modern GraphQL client libraries so that I can take advantage of Pagination, Caching, Mutation and other functions that have been tuned specifically for working with a GraphQL server, so I don't have to re-invent the wheel.  Without getting into a flame war, are there any inherent advantage to either of these frameworks for this application, or do they essentially achieve the same benefits, just in different ways?  Are there any good resources out there that illustrate how to successful use Clojurescript with GraphQL?"

However, in Clojure* land, it sounds like you just need to pick one, and hack away until it works :)           

Thanks again for the feedback and guidance!
-- Nick
 

Nick Pavlica

unread,
Jun 30, 2017, 8:52:40 PM6/30/17
to ClojureScript
Hi Dustin,
  Thanks for addressing my question, and helping me better understand ClojureScript, and the community!


On Friday, June 30, 2017 at 2:35:40 PM UTC-6, Dustin Getz wrote:
It's not clear to me that the cljs community has converged on graphql as a best practice. some people have certainly adopted it but it doesn't feel like there are very many to me. for example, Datomic has been doing what GraphQL offers plus much more since like 2013, it's not clear that graphql adds anything to what cljs users have already been doing since at least as long as facebook is been doing it internally. this isn't what you asked, but could explain the silence.

I'm sure that GraphQL isn't that big of a deal from within the Clojure* community, but it's pretty exciting when you are coming from traditional environments where you deal with REST endpoints.  I've done a little research on Datomic, and it sounds awesome, but I haven't used it yet.  In my mind, GraphQL has some non technical advantages over Datomic.  The primary advantage is that it's an open specification, and not a proprietary product.  This allows for multiple implementations, and provides opportunities for multiple support points.  As it stands, there's only one company that has a Datomic implementation, and if they go down so does your tech stack.  Additionally, if the current implementation of Datomic doesn't have a feature or function you can't just add it yourself(At-least to my knowledge);  Another potential down side of having only one Datomic vendor, is the potential of price gouging leading to unforscene budgeting issues.  I'm saying that Cognitech would act that way, but it's something that I think should at-leas be considered.  I'm sure an end to end Clojure stack, plus Datomic is pretty sweet, I'm just now sure how many can go that route.  It makes me wonder if someone isn't thinking about an open implementation.    

Many Thanks!
-- Nick   

mynomoto

unread,
Jun 30, 2017, 11:28:22 PM6/30/17
to ClojureScript
Hi Nick,

At Xerpa[1], we have being using graphql on a clojurescript project. It's an SPA that uses reagent with json api and its currently being converted to a re-frame one with graphql.

We studied the possibility of using relay modern and apollo client but decided to not use them at the moment.

We started using graphql-builder[2] which is like yesql[3] but for graphql queries meaning that you write queries in another file directly using graphql and you can use those from clojurescript functions passing parameters when needed. It worked really well for the first couple of views but we found it not flexible enough for our needs in different views. 

After more research we found a new library venia[4] that uses clojure data structures to generate graphql queries. We needed a mechanism for merging queries requested by each component and requesting the merged query when the view changed. We wrote that in house and it's in production for a couple of months. I hope to find time to write more about that sometime but this is our experience so far.

Cheers,

mynomoto

Christopher Small

unread,
Jul 1, 2017, 5:19:59 PM7/1/17
to ClojureScript
Hi Nick

I'll try not to get carried away here...

First off, folks in the Clojure and ClojureScript communities are absolutely familiar with, inspired by, and building on top of or in the direction of GraphQL. David Nolen, the author of Om and the lead ClojureScript developer, has build om-next which is more or less a Clojury take on the GraphQL idea. The insight there, which Dustin hints to, is that Datomic has this thing called a pull query you can execute, which is more or less isomorphic (I guess if it's more or less I should just say homomorphic...) to the GraphQL query. Om-next is basically just "let's close that gap", and most of the gap is stuff like pagination and sorting of collections. So it gives you a way of describing these things directly in your pull queries. The nice thing about the pull query, is it's just a data structure, so it's very composable. You can build queries up programatically, which is really lovely. This pattern of building programs around the composition of data structures is really a cornerstone of the Clojure philosophy.

As I think some others have pointed out here, there seem to be others experimenting more directly with the GraphQL api. But om-next is really no less agnostic about a lot of things than GraphQL. It's not really tied to Datomic, except in that it inherits the pull query syntax. But you can implement the resolvers and such to work with any backend storage mechanism (and long as you can traverse the relationships). The Datomic integration happens to be trivial, which is nice, and opens up other possibilities. However, Datomic is not the only "Datomic" in a sense. DataScript is a cljc (meaning, it can compile to and be used from both Clojure AND ClojureScript (And JS actually)) implementation of an in memory version of the Datomic API. It's actually surprisingly feature complete, and a great way to experiment with the underlying data model, pull queries, and even Datalog (a query language also baked into Datomic which is more expressive than SQL, and better for querying graph relations). The folks at Mozilla have also started working on Mentat, a Rust (I believe) implementation of a Datomic like database on top of SQLite. It's very clear to me with all the activity around these projects that while Datomic remains a very powerful system with many features these other projects will likely never aim for, the overall idea has started catching on, and is worth paying attention to.

Part of what makes the om-next approach so fascinating is that Datomic's data model is based on RDF. If you're not familiar with it, RDF is a web standard, and the de facto data language of the Semantic Web (also manifest as web standards). It's part of the vision of the computable web of data. The idea is that all data should be self-describing, globally meaningful, and infinitely extensible. There are vocabularies which can be described in RDF data, which themselves describe the schema and meaning of other data. It's super brilliant stuff, and actually really simple! Data is organized as (entity, attribute, value) triples of "facts". The key is that as long as your attributes are globally meaningful, you can merge information about an entity without ever worrying about overwriting other information about that entity. This gives us extensibility. In Clojure and Datomic, these globally meaninful attributes are achieved via namespaced keywords, which is also: brilliant and simple. We can also have entities that point to other entities, giving us polymorphic entity relationships. Datomic owes some of it's brilliance and I think success to making this collection of ideas a bit simpler, more approachable and more idiomatic. RDF has been a great idea waiting for someone to come around and maximize it. And Datomic is not alone. Look at other companies like MarkLogic who've built big businesses around RDF technology. By contrast, GraphQL is an idea that was hacked together kind of recently, is not as far as I know a standard (please correct me if I'm wrong here), and doesn't have namespaced attributes, so you're a little stuck not being able to get all of the natural polymorphism and extensibility of Datomic and friends as easily. However, it's also proven that streamlining the communication of data from server to client, and stripping out all of our bloated controllers and REST apis is possible, and that it can dramatically shrink code bases and accelerate development, which is really awesome. But in short, it's really worth seeing what the Clojure community is doing with these ideas, because it definitely adds some dimensions of awesomeness.

I'd be remiss if I did not mention that I'm working with some folks on building out Datsync, a system for syncing Datomic/DataScript data (EAV / triple data, in technical terms) between nodes in a network (either server client or P2P). Here, our goal is to extend the scope of what om-next describes by automating the synchronization of EAV triples given that this is what your data looks like. We do plan to support om-next style pull query syntax (so you'd be able to differentially sync using something more or less equivalent to a GraphQL query). But we're also considering implementing a reactive, incrementally maintained, eventually consistent Datalog engine. It's been shown that a subset of Datalog is more or less the most expressive eventually consistent language you can construct, so this effectively means we'll have maxed out what you can describe without needing coordination between peers (and hence some kind of consensus algorithm, like Raft or Paxos). In general, it's a really lovely complement to the pull query. Taking a step back though, the audacious goal of Datsync is to more or less one-up GraphQL by having the full expressiveness of Datalog+pull for the description of synchronization scope, together with the flexibility of RDF data for data modelling, and almost 0 hook-up (you won't have to implement resolvers or anything; just plug in an synchronize). There are some caveats to this of course, and there will be plenty of work exploring this paradigm, but we're very excited by the potentialities!

As for your comments about your experience coming to the Clojure ecosystem, I really appreciate your voice here. The Clojure community is full of extremely bright folks working on lots of really wonderful things, and it can feel a little overwhelming coming to so many new ideas and ways of doing things at once. Having done ruby and rails development in the past prior to Clojure, I can testify to that feeling. So, while I can say that it does get better, there have been discussions in the community of late about how we can reduce the burden here. So again, I thank you for voicing your perception of things here. However, I can also say having poked a stick at various JS tooling that the ClojureScript ecosystem anyway feels way saner to me. There are two build systems, but to at least some extent they are compatible. Contrast that with Python's infinite menagerie of tooling. Also, FP is getting more popular in JS, so folks start bringing in libraries to help with that, and instantly, confusion ensues about which one, how they handle this edge case, etc. In contrast, ClojureScript has good pure data structures built right into the language, as well as all (well, most) of the well thought out functional programming utilities baked into the clojure.core namespace, so there's never a question about any of that. And by building on the Google Closure compiler, ClojureScript is able to leverage a bunch of useful properties of that sytem automatically, without any real thought, such as code shaking, browser compatibility, etc. And yes, it's a little confusing some times figuring out which lib works on front end versus back end, but honestly? This is way better than the alternative in my opinion. What other functional language has as high a utilization across browser, server and distributed system? That's a lot of power to pack into the punch of one well thought out language. So I'd argue that the mild discomfort of coming into the scene and having to figure out what libs are for clojure and which for clojurescript is more or less worth it, cause in the end it's only giving you more options. And I think now that we have .cljc files for doing this, more and more libraries are doing this "first-class" now, and for old libs, they are frequently rewritten to work with both after the fact, so the situation is improving overall. But that doesn't mean there isn't more we can do to make the situation better.

Ok... I think I got carried away... but hopefully that 2c was useful.

Chris

Nick Pavlica

unread,
Jul 5, 2017, 2:12:26 PM7/5/17
to ClojureScript
Hi Mynomoto,
  Thanks for all the good information!  I'll look into venia, and the other tools that you pointed out.

--Nick

Nick Pavlica

unread,
Jul 5, 2017, 2:25:38 PM7/5/17
to ClojureScript
Hi Chris,
  Lots of great information here!  It sounds like your preference is Om(next), which sounds very interesting.  I think that I'll have to dig in and play with it before things really start to click.  I'm sure I'll have many more questions once I get a better handle on Clojurescript approach. 

Thanks Again!!
-- Nick 

Christopher Small

unread,
Jul 5, 2017, 4:43:34 PM7/5/17
to clojur...@googlegroups.com
My pleasure; Happy to have been helpful.

I'll clarify that I think om-next is probably going to be the most Clojuric and well-trod approach to GraphQL style web development with Clojure/Script. However, I personally prefer Reagent over Om. This is part of why I started down the route of developing Datsync. I hoped that I'd be able to decouple from the particulars of the React wrapper (om vs reagent vs rum vs quiescent etc), and have something more standalone. But we're quite a bit further from being generally production ready, so factor that in as you will. And to be clear, I think Om is great, so don't let my preferences steer you away. But maybe also consider tinkering with Reagent a bit for contrast.

Cheers

Chris


--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/VbJLJS9I-qM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescript+unsubscribe@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.

Dustin Getz

unread,
Jul 5, 2017, 6:24:04 PM7/5/17
to clojur...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages