Hacker News new | ask | show | jobs
by bsbechtel 2708 days ago
I recently did a POC for my company on a mature Angular project to see what it would take to switch over to the Apollo stack. I ended up reducing LOC by 50%, adding caching, full offline support, and optimistic UI. I’m convinced if we had used the Apollo stack at the start of the project, our front end resource requirements might’ve been 30-40% less for the project. The things the Apollo team have done are really making a big impact on engineering teams that adopt their tools.
3 comments

I recently tried Apollo for a project as well, for the most part, its almost magic, doing most of the usually tedious things for me. But I often run into unexpected blocker on the most basic functionalities that I need.

One of them that I haven't been able to really solve till now is around cache invalidation / removing deleted items from cache.

How have you been finding Apollo around that area?

I'm currently working on a full-stack app centered around GraphQL and my experience is pretty similar to yours - when it works, it's like magic. The problem is, it doesn't always work the way you expect it to. Here are some of the things I've noticed:

While the main technologies are pretty mature and well documented, gluing them together is often a lot trickier and left entirely to the user. If you need a way for Apollo to communicate with the database, you have to handle that yourself. Same thing for authentication and access control. File uploads also require a separate library.

I think the whole stack has a lot of promise, but it's going to have trouble gaining steam as long as it forces the user to think about these sort of things.

Something else I've noticed is that it shifts a lot of the work to the back-end while at the same time introducing new problems you never had with REST. With REST, you had endpoints with clearly defined inputs and outputs, which were easy to reason about and secure. This is not the case with GraphQL - because it is so expressive, it's hard to cover every possible use case, especially if you're doing the entire security and access control yourself. The other problem GraphQL has that REST does not is recursive queries - it's entirely possible to request something like this:

authors -> posts -> comments -> authors -> posts -> comments ...

Another thing I should mention - while Prisma and Apollo are pretty stable and well documented, various smaller libraries are often not. This is not an issue specific to GraphQL, but because it has a smaller ecosystem then say, React, you're a lot more likely to run into it.

Lastly - the pace of the development is bonkers. I've run into situations where an 8 month old post was already obsolete. Or major versions a year and a half apart.

I lot of the issues you mentioned really are meant to address problems faced by teams working on a project at scale. I really didn't understand the need for GraphQL until I was put on a project where we had multiple REST endpoints we needed to query data from, new people were joining every week, and communication + data requests across different teams required a significant portion of everyone's time.

The issues you mentioned are issues if you want one (or a few) framework or library to handle all of your web development needs, but rarely does one library work for web development at scale.

It sounds like your issue was with poor documentation and not some fault inherent to REST itself. I don't think that just switching to GraphQL is going to fix that problem (though Playground is a pretty nice way of getting to know the API).

I guess my main qualm was that, because GraphQL does a relatively poor job of explaining why you should use it, people like me get the wrong idea about what kind of problems it solves and why you should use it instead of REST.

It's not really an issue with documentation within our team. It's an issue of having hundreds of REST endpoints (all which need to be learned by new devs), multiple local dev servers running on your machine to mimic those endpoints, and an excess of work done on the front end to merge data from across those REST endpoints once it all arrives on the client. Additionally we would get requests from other teams wanting to access data, so instead of them just writing a query to the same GQL endpoint we all share, we have to write a new endpoint for them, manage access control on that endpoint, etc. These are the issues GQL solves.
My personal major pain point with Apollo is with the need to manually manipulate the cache to keep it in sync after a mutation that adds or removes an item from a list, which feels really clunky and error prone compared to the much more elegant workflow of updating an individual entity, where the cache gets updated automatically by Apollo's normalization. See https://www.apollographql.com/docs/angular/features/caching....

Ideally I'd like to be able to specify a unique identifier for a list through a directive on a query, and then specify the same identifier on the mutation, to have the result of the list in the mutation automatically replace the contents of that key in the cache (or append onto it for use cases like pagination, possibly in combination with another directive for sorting the combined list on the client-side?).

I was hoping to be able to do something like this using the @connection directive: https://www.apollographql.com/docs/react/features/pagination...

Unfortunately, when I tried this it looks like the @connection directive actually creates separate nested keys for mutations vs queries, so unfortunately this use case isn't possible yet. I'd love to hear how others are approaching this problem, especially those using other caching graphql clients like Relay. Or maybe I'm missing some better way to handle this in Apollo itself?

If you use fragments you shouldn't need to write update logic. Also you can use `dataIdFromObject` on your apollo cache to control how unique ids are done.
Curious how fragments can be applied to the use case of creating a new item and having a query for the list of items updated automatically? For instance, in the createTodo mutation & todos query example here: https://www.apollographql.com/docs/angular/features/caching....

I was hoping to be able to expose the list of todos on the createTodo mutation response, and have Apollo update the cache automatically by querying for it in the mutation response, rather than writing the newly created item to the appropriate location in the cache manually. From my research into it so far, it looks like that's not currently possible, but I'd love to be wrong about that!

I'm not sure what you're pointing to, but are you suggesting to ignore the cache? Coz that is basically what I currently do. Throw away the cache for the lists, and fetch a fresh one everytime. While that "works", but it also throws away lots of the supposed benefits that Apollo brings to the table, and its also rather awkward when you need to "trigger" the fetch manually when the display doesn't involve something like page navigation
Imo “cache management” is outside of the Apollo scope. Everyone’s specific cache requirements are different and you should just implement your own.
Actually you can directly read and write the cache with the readQuery command. You can see it here https://www.apollographql.com/docs/react/advanced/caching.ht...
this doesn't work when you have a query with any sort of variables. for instance if a query that returns SortBy "Name" and the user changes the sort to be "Email", now you have two queries you would need to call readQuery on and update, and that means you need to track all query variables and all affected queries for a delete. It just doesn't work. See https://github.com/apollographql/apollo-feature-requests/iss... and the numerous threads of people expounding on this issue.
This 100%. Luckily, it is their number 1 feature request for version 3.0 See https://github.com/apollographql/apollo-feature-requests/iss... for more details.

I LOVE how great Apollo has made my dev experience on the frontend. Cache invalidation is a hard problem though and I don't blame them for not tackling it until version 3.0.

The fact that they can already update data based off of fragments for all queries observing the fragment makes me believe they could extend a similar solution to invalidate a fragment and have subscribed queries remove that fragment.

Yes, fetch policy works well and also rest/clearCache for logout. I haven’t really had any issues where I’ve needed anything beyond what’s offered there.
The downside is that if you are building in React Native, you don't want to run queries every single time the user does something and eat up all their data. But this is what I am resorting to until 3.0 comes out with cache invalidation strategies.
What was the stack you used for the graphql part ? I'm keen on understanding what the migration path from REST to graphql looks like (with all your data in a relational DB).

Could you write a bit more about your learnings here ?

Sure...just a quick overview, but I used Apollo Client on the front end with a few different Apollo Link packages to handle retries, offline queueing, and batching. I set up the grapqhl server as a middle layer using an Apollo server serverless instance. This graphql function then relies on the RESTDataSource package to hook up to various back end APIs.
What is the Apollo stack? Do you mean GraphQL in the frontend?
Generally I would assume an Apollo stack would have an Apollo server [1] or an Apollo client [2] or both. GraphQL on the other hand is just a query language. GraphQL queries are used by Apollo Client to ask for data from a GraphQL endpoint which could be provided by an Apollo Server or some other GraphQL server implementation.

By my inspection it seems the only official Apollo Server implementation is in Node.js. By my understanding, you can replace an Apollo Server with any GraphQL server for example Scala's Sangria [3]. So, your Apollo Client can talk to any GraphQL server, and Apollo Client is probably the best and most useful part of an Apollo stack anyways.

One good website for figuring out how to use different Apollo stacks is howtographql.com [4] (I am not affiliated with them, but I only like their service.) It has free tutorials for GraphQL servers including Elixir, Python, Node.js, Scala, Ruby, and Java. Howtographql also has a React and Apollo Client tutorial.

All Apollo Clients include:

JavaScript:

- React

- Angular

- Vue

- Meteor

- Ember

Web Components:

- Polymer

- lit-apollo

Native mobile:

- Native iOS with Swift

- Native Android with Java

- React Native

[1]: https://www.apollographql.com/docs/apollo-server/

[2]: https://www.apollographql.com/docs/react/

[3]: https://github.com/sangria-graphql/sangria

[4]: https://www.howtographql.com