6 ms·
Core Contributor of urql here, another JS GraphQL client. I think this post is very good at stating why the particular post it’s referencing (“Why GraphQL” in
by philplckthun 6y ago
Core Contributor of urql here, another JS GraphQL client.
I think this post is very good at stating why the particular post it’s referencing (“Why GraphQL” in the Apollo docs) isn’t a full picture overview, and it succeeds at that very well, but I think it doesn’t go on to expand on these views just as much as I’d like to.
If we look at popular comments by the GraphQL community on this it isn’t hard to find that “the quickest & easiest client is to just fetch a GraphQL API” (similarly said quite frequently) and that’s an excellent point.
But going on to say:
> However, you should always consider the cost of adding a GraphQL client to your frontend.
This is definitely true, but as a creator of another GraphQL client I’d say that there are major benefits as well, the main selling point of Apollo, Relay and urql (for the latter this is optional) being that you can utilise a normalized cache.
But these tools often provide great frameworks to solve some of the problems that are stated to be woes with GraphQL, like persisted queries, subscriptions, file uploads, etc. So they’re a great starting point to dip into multiple parts of the community and get out-of-the-box solutions for your problems.
And generally I’d say that sums up GraphQL: it’s not novel or anything new. Instead it combines a lot of ideas into a solid community and ecosystem. With tools like Swagger or gRPC it’s easy to see how any part we look at for GraphQL isn’t novel.
What is great is that the exact set of problems it solves it does so with a larger (and growing) community and a standard that encompasses multiple of these solutions.
Finally, I’d say again, GraphQL clients and servers aren’t “all of GraphQL,” Apollo isn’t GraphQL (although they’ve made themselves synonymous with it) and hence there are different tools, clients, and libraries to create GraphQL servers, clients, and interact with GraphQL APIs. As a user you’ll still have to choose, but a lot of the good parts come from agreeing on one language and standard that allows for introspection and the ease using which we interact with these APIs on the client-side, from simple HTTP calls to more complex caching clients.
- jensneuse 6y agoHey, thanks for your reply. I think you guys have done an amazing job creating a very powerful GraphQL client. However, to me "smart" GraphQL clients don't make much sense. My approach with WunderGraph is the following: You write down all your Operations using GraphiQL. We automatically persist them on the server (WunderNode) and generate a "dumb" typesafe client. This client feels like GraphQL and behaves like GraphQL but is not using GraphQL at all. It's just RPC. This makes using GraphQL more performant and secure at the same time. Additionally it's a lot less code and a smaller client because those RPC's are a lot simpler.
- rattray 6y agoThat sounds really cool! But I don't think it addresses why I'd want a "smart" GraphQL client: normalized caching on the client. Say I have a dashboard where multiple panels on a given page make their own requests, since the panels are shared between many pages. But they share some objects. If I get updated data in a request from one panel, I'd like to see that update in all panels, without triggering more requests. Side note that a magic layer to have each of those components combine their requests into one would actually hurt performance, since it's better to load the requests in parallel. And manually merging them into one would be quite a chore.
- jensneuse 6y agoClient side caching with a normalized cache implementation is very hard to get right. I see why you would want that feature and if it were simple to implement I'd always want to use it. However I think we can get away with a solution that is a lot simpler than normalized caching. With persisted Queries we can apply the "stale while revalidate" pattern. This means we can invalidate each individual page and would have to re-fetch each page in case something updated. This is some overhead but the user experience is still very good. Normalized caching in the client can get super hairy with nested data. In addition, normalized caching adds a lot of business logic to the client which makes it hard to understand the actual source of truth. From a mental model it's a lot simpler if the server dictates the state and the client doesn't override it. If you allow the client to have a normalized cache the source of truth is shared between client and server. This might lead to bugs and generally makes the code more complicated than it needs to be. Is it really that bad to re-fetch a table? I guess most of the time it's not. I've written a blog post on the topic if you want to expand on it further: https://wundergraph.com/blog/2020/09/11/the-case-against-normalized-caching-in-graphql https://wundergraph.com/blog/2020/09/11/the-case-against-nor...
- rattray 6y ago> Client side caching with a normalized cache implementation is very hard to get right Absolutely true! When I worked on this at $prevCo, it was tricky and sometimes caused bugs, unexpected behavior, and confused colleagues. I will say that a proper implementation of a normalized cache on the client must have an ~inherent (thus generated) understanding of the object graph. It also must provide simple control of "whether to cache" at each request. Most of the problems we experienced were a result of the first constraint not being fully satisfied. My impression is that Apollo does a good job on both of these but I haven't used it so I can't say. I'll also note that the approach of "when one component makes an update, tell all other components on the page to refetch" sounds like a recipe for problems too – excess server/db load, unrelated data changing in front of users' eyes (and weird hacks to prevent this), etc. Of course, with the wundergraph architecture, it sounds like answer to these questions would simply be to load a given table only once per page – which means no more defining queries on the "panel" components in the dashboard, for example. All tricky tradeoffs! The right answer depends on what you're building. The Wundergraph approach sounds pretty cool for a lot of cases!