The learning curve for Apollo is a bit shallower for two reasons: (1) they have GraphQL libraries that allow you to implement a Relay-like client on top of an existing GraphQL end point (Relay requires some custom fields); and (2) better documentation.
We went with Relay, however, because it is, in my experience, more robust and more polished. The way that Relay handles fragment composition and defers component rendering, along with data masking, is much nicer and more... holistically considered(again, in my opinion). Using Apollo can feel a bit like patchwork sometimes.
Plus, ultimately, Relay is backed by Facebook and used in Facebook applications, in production, so it's not going anywhere.
We're going to write some more content in the coming days or weeks about the differences, but here are some of my main thoughts based on following along during Relay Modern development:
1. Relay uses a build process to generate code for queries. That allows some better performance optimizations and static typing out of the box. However, it prevents you from doing anything which requires arbitrary knowledge of the queries at runtime. It also means that if, for some reason, you can't use the build tooling, you can't use Relay. That's actually the original reason we started working on Apollo instead of using Relay ourselves. Apollo works with regular GraphQL ASTs at runtime, so you can use and write tools to work with those queries in any way you like. While it's not something all apps need, we've found some situations where this is desirable, especially for developers building companion libraries.
2. Relay doesn't have as many facilities for updating the store and working with mutation results. Apollo Client has a unique way to use GraphQL fragments and queries to read and write to/from the store, the most recent of which is described here: https://dev-blog.apollodata.com/apollo-clients-new-imperativ...
3. The Apollo Store is a plain JavaScript object, which means it can be easily serialized, persisted, hydrated, etc. So for example doing server-side rendering where you also hydrate the state is super simple in Apollo. Part of this is because of Apollo's Redux heritage.
4. Developer tools - we think it's super important to understand exactly what is going on with your data, both inside your app and across the wire. That's why in addition to sticking to simple plain objects we worked on some developer tools for chrome: https://dev-blog.apollodata.com/apollo-client-developer-tool...
5. One thing we're really proud of is how different libraries in the Apollo ecosystem are owned and maintained by different organizations from the community. This might make the experience of using it a bit less polished, but means that you can easily contribute or start your own projects if you need some non-standard features.
However, it's also great to remark on the similarities, which I think show that the community and Facebook are converging on some common good ideas. In fact, a lot of the initial decisions on Apollo are based on talking to the GraphQL team at facebook about their experiences:
1. Fully static queries - both Apollo and Relay encourage you to write your queries in the GraphQL language, and avoid manipulating them in unpredictable ways. This is actually one of the ways Apollo diverged from the original Relay release and it's great that it's coming together. Read more here: https://dev-blog.apollodata.com/5-benefits-of-static-graphql...
2. Colocation of data with the view - both Apollo and Relay enable you to do this. This pattern was one of the best achievements of the original versions of Relay, and we think putting the queries and fragments right next to the UI is a great pattern.
Most importantly, though, it's super encouraging that the GraphQL community is gaining another great tool. The best part about GraphQL is the diversity of approaches to servers, clients, and tooling, and that they can all work together through the specification. Really excited to see this release, and I hope we can all learn from each other and make GraphQL a real pleasure to work with.
This is a pretty good distillation of some differences, but I just wanted to reiterate that I'm more excited about the similarities. Having options for what tools to use along with GraphQL is a great thing, and even better is when the best ideas make their way into many of them.
From what I know of Apollo (which is a lot less than Relay, having worked on the RelayModern compiler), this comparison is pretty good.
(1) is true, for the most part, from the developer point of view. But when you're using the compatibility mode of RelayModern (i.e. sending out a legacy query that contains modern fragments), Relay does runtime query building from the Modern fragments.
(2) Relay allows you to define updaters for mutations, which lets you write client-defined data transformations. This may not be as complex as what's happening in the Apollo client, but I don't have the experience to say. See http://facebook.github.io/relay/docs/mutations.html#updating...
Edit: I'm Matt, and I work on a sibling team to Relay at Facebook, and helped build RelayModern's compiler.
Agree that this is overall accurate, especially wrt to Relay Classic. For Relay Modern, however:
> 2. Relay doesn't have as many facilities for updating the store and working with mutation results.
Apollo and Relay Modern are about equal in this regard. Relay supports arbitrary writes to the store (either via an imperative API, via a fragment + payload, or a mix of the two), plus similar APIs for updating the store after a mutation or subscription update. This includes the ability to update client-only state.
> 3. The Apollo Store is a plain JavaScript object,
The Relay Modern store is also a plain object. There aren't currently any convenience functions for serializing/deserializing it, but this is something we're open to adding.
Overall I'd say the main differences is that Apollo has focused very much on easier onboarding and covering a wide variety of use cases (many view layer integrations, developer tooling etc), where Relay is more focused on performance and scalability (hence features such as ahead-of-time optimization, garbage collection, etc).
Either are appropriate depending on your specific needs. I'm excited to see so much iteration in this space!
We went with Relay, however, because it is, in my experience, more robust and more polished. The way that Relay handles fragment composition and defers component rendering, along with data masking, is much nicer and more... holistically considered(again, in my opinion). Using Apollo can feel a bit like patchwork sometimes.
Plus, ultimately, Relay is backed by Facebook and used in Facebook applications, in production, so it's not going anywhere.