11 ms·
Relay Modern: Simpler, faster, more extensible
- deleted 9y ago[deleted]
- jankassens 9y agoHey, Jan here together with Lee from the Relay team. Happy to answer your questions.
- sAbakumoff 9y agoIs it possible to use Relay along with Golang backend that serves graphQL queries via web socket?
- weixiyen 9y agoThanks Jan. Will there be support for websockets?
- josephsavona 9y agoHi, I'm Joe also on the Relay team. Relay Modern (as with previous versions) supports an injectable network layer. This allows each application to customize how to communicate with its GraphQL server using whatever transport protocol is most appropriate (for example you might use HTTP for queries/mutations and WebSockets for subscriptions).
- willchen 9y agoCongrats on the release. Could you summarize the pros and cons of picking Relay Modern vs Apollo Client?
- schickling 9y agoHere is a detailed comparison between Apollo and Relay: https://www.graph.cool/docs/tutorials/relay-vs-apollo-iechu0shia/ https://www.graph.cool/docs/tutorials/relay-vs-apollo-iechu0... (Note: This article hasn't been updated for Relay Modern yet but the main points are still the same.)
- djmashko2 9y agoI think the comparison is going to be pretty different for Modern because Relay Modern has some significant changes in the approach.
- schickling 9y agoYou're absolutely right, we're already working on an updated version. We'd love to have Apollo's feedback on it to make it as helpful as possible!
- johntran 9y ago1. Could you two do a Reactiflux Q&A? 2. Are people on the Relay OSS team willing to answer StackOverflow-type questions on a certain time? - I would want to be able to programmatically run relay-compiler. Every time I update my client-side code, webpack detects the change and then runs relay-compiler. - And get help figure out some errors related to mutations I'm encountering. I wouldn't want to post these type of things as a GitHub issue because it could technically not be a bug.
- leebyron 9y agoHi, I'm Lee from the GraphQL/Relay team 1. Reactiflux Q&A is a great idea, perhaps someone who organizes that can help set that up. 2. We're a pretty small team and our primary focus is building great software for Facebook and the larger community, so unfortunately our ability to focus on answering questions is relatively limited. Many people on the team occasionally hop into StackOverflow to answer questions, but we definitely can't make any guarantees about answering them all or answering them in a certain amount of time. You can run relay-compiler as part of your webpack config as a pre-compile step. Also, if you want to run relay-compiler while you're iterating on your code, pass --watch and it will rerun whenever a file is saved.
- vning93 9y agoHi Lee, Vince here from Scaphold.io. I can help put you in touch with the guys who run the channel and manage the Q&As. We're actually doing one ourselves on April 27. I'll reach out on the GraphQL Slack channel.
- RaitoBezarius 9y agoThanks Jan, what are the remaining pain points to your opinion with the usage of Relay in a modern web app?
- jankassens 9y agoWe've moved from runtime generation of queries to 100% of queries generated at compile time to remove a large chunk of computation out of runtime. Some APIs got more complicated to use than I'd like to. For example, pagination currently requires developers to write an explicit query to fetch more entries. Now with performance in good shape, I want to focus on improving the developer experience again in a way that doesn't sacrifice runtime speed. For example for pagination, we should in most cases be able to synthesize a query at compile time instead of asking for an explicit query.
- tonyhb 9y ago> "Relay Modern is designed from the start to support garbage collection — that is, cache eviction — in which GraphQL data that is no longer used by any views can be removed from the cache" Could we go ahead and implement proper caching as HTTP would do: expiration date per field/models, then eviction based on expiration dates? With an optional max cache size using LIFO, last used or the current model. That way we don't need to refetch data if the API is set up to cache. It's sort of frustrating that staleness is just defacto ignored by UI right now.
- RaitoBezarius 9y agoCorrect me if I'm wrong : But, wouldn't "garbage collection" solve the problem of many React web apps of consuming too much RAM (e.g. when using Redux, you never expire some keys and throughout the application lifecycle, you never cease of accumulating data inside your stores which makes RAM consumption goes up) ?
- josephsavona 9y agoIn general yes, garbage collection in Relay Modern is meant to help constrain growth of memory usage during the course of a session. This is where the declarative nature of GraphQL is helpful; unlike Redux which is accessed via arbitrary selector functions, Relay knows (via queries, fragments, etc) which parts of the cache may still be referenced and can evict records that aren't.
- josephsavona 9y agoHi! I'm Joe from the Relay team. Good questions! It isn't quite as straightforward as you might expect - the interconnected nature of graph-like data means that strategies that work for HTTP don't necessarily apply. For example, storing per-field expiration times could incur additional memory overhead (you might end up with an object per field instead of per record). Storing per-record expiration times is tricky since the same record can have different fields fetched at different times. And a simple max cache size + LIFO/LRU/etc evication strategy means that the cache might evict a record that is still referenced by a view. This type of TTL/expiration is something that we're continuing to explore.
- StreamBright 9y agoIs there any great libraries to implement the backend for GraphQL? I think the benefits of using GraphQL on the frontend are pretty obvious, however last time I checked I had trouble of finding good documentation or implementation on how to serve GraphQL requests from the backend point of view.
- superquest 9y agoGraphene is nice for Python. Supports Relay stuff too (I've never used these features, though). http://graphene-python.org/ http://graphene-python.org/
- weeksie 9y agoAbsinthe works great for me: http://absinthe-graphql.org/ http://absinthe-graphql.org/
- ddispaltro 9y agoSangria over on the Scala side is really nice. http://sangria-graphql.org/ http://sangria-graphql.org/
- krschultz 9y agoThere's a reasonable set of language specific libraries listed here: http://graphql.org/code/ http://graphql.org/code/ Also a common pattern is wrapping an existing REST API with a GraphQL proxy: https://github.com/graphql/graphql-js https://github.com/graphql/graphql-js
- schickling 9y agoFor frontend developers who want to get started quickly, you can also use a hosted GraphQL service such as Graphcool: https://www.graph.cool https://www.graph.cool This approach abstracts all of the implementation details away and lets you focus on your GraphQL schema + implementing your business logic. Disclaimer: I'm one of the founders of Graphcool. Happy to answer any kind of questions!
- leebyron 9y agoThere are many great libraries for backends available in many different languages. Some resources to find one: http://graphql.org/code/ http://graphql.org/code/ https://github.com/chentsulin/awesome-graphql https://github.com/chentsulin/awesome-graphql
- schickling 9y agoI'm super excited about this release! Great work Jan, Lee, Joe and everybody else who was working on this! :) At Graphcool (https://www.graph.cool/ https://www.graph.cool/) we were using Relay since the very beginning. It has enabled us to build frontend products at an incredible speed and while staying confident about the data layer. For instance our entire console is written using Relay at its core. (It's open-source btw: https://github.com/graphcool/console https://github.com/graphcool/console) PS: We're also the authors of Learn Relay (https://www.learnrelay.org/ https://www.learnrelay.org/) which we'll update to Modern Relay soon!
- orta 9y agoCongrats! Relay is what really sold our iOS-only native team to move to React Native. Very excited to migrate to modern version at some point in the future. ( http://artsy.github.io/blog/2017/02/05/Retrospective-Swift-at-Artsy/#Better.Abstractions..Better.Developer.Experience http://artsy.github.io/blog/2017/02/05/Retrospective-Swift-a... )
- misiti3780 9y agois emission the only react-native app artsy has built/open sourced?
- orta 9y agoYes, it's the only React native we have apart from trivial demo apps to prove a concept (which stay on a user's repo rather than the artsy org )
- ianstormtaylor 9y agoWhat are the differences between Apollo and Relay Modern at this point? Why/when should you choose one over the other?
- schickling 9y agoHere is a detailed comparison between Apollo and Relay: https://www.graph.cool/docs/tutorials/relay-vs-apollo-iechu0shia/ https://www.graph.cool/docs/tutorials/relay-vs-apollo-iechu0... (Note: This article hasn't been updated for Relay Modern yet but the main points are still the same.)
- voxmatt 9y agoThe 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.
- linkmotif 9y ago> Plus, ultimately, Relay is backed by Facebook and used in Facebook applications, in production, so it's not going anywhere. That's why I went with a Relay too. But I have a feeling that Relay will not be long for this world. I just feel it in my bones.
- djmashko2 9y agoHi, I'm from the Apollo Client team. 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-imperative-store-api-6cb69318a1e3 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-tools-ff89181ebcf 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-queries-b7fa90b0b69a 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.
- cainlevy 9y agoI'd be interested to read an analysis of how this compares to the backends-for-frontends pattern. Also, it seems like Relay Modern reintroduces API versioning, but automates it behind a compiler step. Is that a fair characterization? Does the server have to implement some kind of tracking and pruning for unused fragments, or is it expected that the fragments will accumulate at a non-threatening rate and never need pruning?
- foota 9y agoI wouldn't say so, this has none of the maintenance implications that versioning does.
- cainlevy 9y agoOh? Seems like you still want to support old client versions, which means retaining the fragments that they reference. The question then is what implications that has on a server -- do old fragments need to be eventually garbage collected?
- foota 9y agoThat is fair, I hadn't thought of that. I would argue the difference is perhaps the ease of tracking the different versions and their usage and the ease of collecting versions. Plus the client can fall back to submitting the full query.
- leebyron 9y agoHi, I'm Lee from the GraphQL/Relay team This technique of persisting the queries (and fragments) to the server at build time predates Relay - we've been using it on our iOS and Android apps since 2013. At build time these clients submit their query strings to the server and get a small identifier in return which they can use at runtime to reference the whole query. This definitely means that old queries need to be kept around as long as the clients that use them are still active. Since iOS and Android apps seem to last forever, we're still getting traffic today from just about every version of our native apps we've ever shipped, even from 2012 and 2013. Because of this we decided to not bother with garbage collecting persisted queries, in terms of all the other data Facebook retains, persisted GraphQL queries is a grain of sand in a desert. However, with a bit more work, you could easily keep a hit counter per persisted query and go remove any persisted queries which had no recent hits.
- voxmatt 9y agoExciting to see! I've been waiting on this since we decided to use Relay for our application about 6 months ago. Relay is amazing but quite an investment (especially mutations). I'm a bit worried, however, that Relay Modern has focused a bit too much on the internal needs of a massive application like Facebook at the expense of fleshing out some of the rough spots of working with Relay. Simpler, more explicit mutations is a wonderful improvement, as is more granular control over the cache, but there's no mention of subscriptions or client-side state control (using Redux on top of Relay is... doable, but not as elegant as one might hope for). That all said, this is an impressive release and congratulations to the team. We're committed to Relay and hope this release grows the community.
- voxmatt 9y agoFollow-up (didn't see the updated docs). Looks like there is some support for client-side state through "Client Schema Extensions" — excited to play with this. I do also hope that this iteration brings with it better docs — that's the one area where I've looked over at Apollo longingly. On many occasions I've discovered unknown patterns in stack overflow answers that aren't documented anywhere (credit where it's due: the answers are often by members of the Relay team). And one final tangent: the day when Facebook gives up on flow and adopts Typescript will be a glorious, glorious day. More here: https://facebook.github.io/relay/docs/new-in-relay-modern.html https://facebook.github.io/relay/docs/new-in-relay-modern.ht...
- wincent 9y ago> I do also hope that this iteration brings with it better docs The docs are very minimal this point with some definite gaps (we had a bit of a scramble to get them written in time for F8), but the point is well-taken: Relay docs need to get better. Luckily, the design of Relay Modern is simpler and easier to understand and explain; there is less (no?) magic involved, so we should be able to get the docs to a much better place now.
- linkmotif 9y agoNow that mutations are so much simpler, would be great if there was some discussion of what you get from connections. Previously this was only well explained in blog posts by Huey Petersen. Thank you!
- pducks32 9y agoFacebook has said that they never remove a property from their databases which seemed nuts to me but with Relay and GraphQL it makes a lot of sense. Why have the need for versioning when the client can request whatever they need.
- leebyron 9y agoHi, Lee from the GraphQL/Relay team. To clarify a bit: we've removed fields from and changed our database schema repeatedly over the years. In fact we've migrated between entire database technologies multiple times over. What we haven't done is remove fields from our GraphQL API when those fields are still in use by shipped iOS, Android, or web apps. GraphQL gives us a layer of abstraction to create consistency from the point of view of client apps while allowing iteration of backend services.
- pducks32 9y agoOh hey thanks for the reply. I think I misunderstood before. But what you are saying is what I meant to say. That GraphQL is fantastic in that it gives a layer of abstraction away from versions apis with different endpoints.
- ilovecaching 9y agoMy biggest gripe with the original Relay was that it didn't work with any GraphQl schema, but only those that provided a bunch of features like pagination and retrieving any object by id. This no batteries included, high initial bar for using Relay really turned me off of the product. I see that Relay Modern claims to be 'simpler', but I don't see anything about relaxing the constraints on my graphql schema.
- mjmahone17 9y agoYou should be able to use Relay Modern with any valid GraphQL Schema. If you can't, it's a bug that you should create an issue for! To use your own schema, you just need to specify what it is during the relay-compile step: http://facebook.github.io/relay/docs/relay-compiler.html#setting-up-relay-compiler http://facebook.github.io/relay/docs/relay-compiler.html#set...
- ilovecaching 9y agoSo are you saying that http://facebook.github.io/relay/docs/graphql-relay-specification.html http://facebook.github.io/relay/docs/graphql-relay-specifica... no longer applies to Relay Modern? I can use any schema and Relay will just work?
- mjmahone17 9y agoYes, mostly: if you don't meet the first requirement (having some sort of root field that allows you to refetch an object), you'll have trouble using, for example, RelayModern's RefetchContainer. If you don't meet the second requirement (a description of how to page through connections), you'll need to define how to paginate through connections as part of your component's logic (if that matters to you). And the third requirement: you no longer need to use Relay's imperative mutation API. You can simply describe a specific mutation to refetch, including all of the fields (i.e. via a fragment) that you want fetched every time you send that mutation (fat queries are gone in RelayModern).
- 9y ago
- vidar 9y agoMaybe I am way off base but "Colocation of data and view" reminds of awful PHP with SQL interspersed with HTML and CSS. Am I wrong?
- leebyron 9y agoHi, Lee from the GraphQL/Relay team here You're not off base at all! It's very similar to that. I think it's important to extract what was good and bad about this old website pattern. The good is that within a single PHP file you could see both the logic for requesting data (SQL) AND the logic for rendering that data. This colocation was part of what made the early web take off, it was a great developer experience. The bad is that these interspersed SQL statements were immediately invoked and blocking, which led to utterly awful performance. One of the core ideas of Relay is that we wanted to bring back that developer experience of colocation while not only retaining good network performance, but actually creating opportunities for network optimization. When you see GraphQL in your Relay code, that is not a blocking immediately invoked network request. It's a description of a part of data needed. Relay aggregates these GraphQL fragments together to submit in few network requests in a non-blocking way to achieve the network performance we expect from modern mobile applications.
- davidjnelson 9y agoEdit: Nevermind, this has already been answered. Anyone have insight on relay modern vs apollo? http://www.apollodata.com http://www.apollodata.com
- djmashko2 9y agoFor anyone that comes along, I answered in this comment: https://news.ycombinator.com/item?id=14143112 https://news.ycombinator.com/item?id=14143112
- Untit1ed 9y agoStill can't see anything about making server-side rendering a first class citizen for relay :(.
- vning93 9y agoCongrats on the release of Relay Modern guys! This has been a long awaited moment :)
- vladgur 9y agoI'm curious how this compares to Apollo Client 1.0 which was released this week
- djmashko2 9y agoI answered in this comment: https://news.ycombinator.com/item?id=14143112 https://news.ycombinator.com/item?id=14143112
- WhitneyLand 9y agoIt seems many people loved GraphQL, a powerful and elegant concept, but then had a rude awakening with Relay as an overly complex, unwieldy, buzz kill. Node, edge, and viewer are terrible mistakes w.r.t. naming and usability. I'm sure it's very intuitive for FB devs to think in these terms, but the words are specific to a problem domain and just don't translate as well to the general case as other choices might have.
- sgift 9y agoThat was one of the reasons I ran as fast as possible to Apollo after trying to understand Relay for a bit (that and more or less no tutorials for Relay). The other one was that Relay seems to be one of these "my way or the highway" frameworks, while I prefer libraries which follow my needs and don't force me to do all things the way they want.
- dasmoth 9y agoI've been somewhat out of the Clojurescript loop recently, but this looks conceptually a lot like the om.next model ("colocated queries"). Makes me curious how many people are using om.next in anger. It's always seemed like a good idea (and now with some extra endorsement for the core principle), but judging by GitHub activity (which I realise isn't a perfect measure), the project seems to have rather lost momentum.
- darkmirage 9y agoI work at Facebook and had the chance to use Relay Modern for an upcoming product. Was really happy with the performance and collocation of data and view just amazing. Love it :) BTW I realized where Relay's logo came from by chance while fiddling around with PowerPoint's new Morph transitions... https://gfycat.com/EnviousBothFinch https://gfycat.com/EnviousBothFinch
- TimMurnaghan 9y agoOne of the things that I've noticed about the javascript community is that they're re-inventing stuff from previous technologies - sometimes badly - but almost always with a willful ignorance of what has gone before. While this doesn't look like a bad idea - what they've done is to re-invent stored procedures. Back in the original object orientated wars this turned out to be a mixed blessing. You could get quite sharp performance, but reasoning about the application logic became harder. It might be nice if this kind of issue was at least acknowledged in the article.
- dboreham 9y agoI don't think this is what they have done. They've invented a client/server data model, schema definition and associated query language. Definitely wheel-reinventing, but imho a useful valid wheel which stored procedures were not. If it were like stored procedures the relay code would be running on the server. It runs in the client.
- Meai 9y agoSeriously, your own homegrown garbage collection inside the js runtime? I looked at React the first time it came out and aside from the insanity of using xml mixed with javascript or some kind of pseudo js, it was waaaay too complex. I dont know but it seems crazy to me to write applications like that, it makes xaml look decently simple.
- theprotocol 9y agoI still firmly believe riot.js (http://riotjs.com/ http://riotjs.com/) is the best "react-like" tool even though it's almost entirely unknown (sadly) and its website/PR/general presentation is a bit janky. It's essentially a very very tiny, minimally opinionated structural layer that lets you build html components (called "tags") using almost entirely vanilla JS. It inverts the JSX paradigm: where JSX is "html in the middle of your code", in riot the markup is primary and the code is a supplement to it (expressions in the markup via templates/mustaches, additional tag-specific script added outside of the markup if desired, tag-specific scoped css) so there's no JSX insanity. It's like a much leaner react/vue, and frankly I love it. It's entirely minimal and you can bring in any library you want to use along with it (e.g. jquery for ajax, redux if you want...). It has virtually no cognitive load (just looking at a sample "tag" file for 2 minutes gives you ~80% of what you need to know), you just pick it up and work with it and just occasionally peek at the docs if needed. I'm a huge fan of the "minimally opinionated" approach. The fewer idiosyncrasies and custom abstractions in tools, the more productive you are (I'm looking at you, angular!).
- vog 9y agoI also found Riot very practical, mostly because I got up and running very quickly. I had a well-structured Riot app done faster than grasping all that ReactJS boilerplate. And this was possible even though the Riot documentation was sub-optimal in some places, to say the least - the holes in the documentation were compensated by the fact that most things are simple and straight forward. I don't know how good this concept scales to huge applications, but I can confirm that writing a non-trivial SPA in Riot was a charme. Neverthelss, I do miss some things the Riot for the overall architecture and information flow. But I learned that ReactJS doesn't have these either. As with React, Riot should be combined with Flux, or a lightweight alternative such as Redux.
- acjohnson55 9y agoHow is it that they make an announcement like this without any actual code in it?
- marcosscriven 9y agoStruck by this para: "The native app teams discovered that using GraphQL came with the additional overhead of building queries by concatenating a bunch of strings and then uploading those queries over slow connections. These queries could sometimes grow into the tens of thousands of lines of GraphQL. Also, every mobile device running the same app was sending largely the same queries. The teams realized that if the GraphQL queries instead were statically known — that is, they were not altered by runtime conditions — then they could be constructed once during development time and saved on the Facebook servers, and replaced in the mobile app with a tiny identifier. With this approach, the app sends the identifier along with some GraphQL variables, and the Facebook server knows which query to run. No more overhead, massively reduced network traffic, and much faster mobile apps." Firstly, what query could be 10k lines? Secondly, if you're defining the query just by an id, how is that then any different to a fixed REST endpoint or stored procedure?
- naked-ferret 9y agoThis is the most hilarious part of the post. I'm glad someone else caught that too!
- acjohnson55 9y agoA 10k line query is pretty easy for me to imagine. In GraphQL, every property you want on every object is a line, since you query by property, not by object. In an interface with a whole bunch of widgets, I can imagine it really adding up. It _is_ pretty much like a stored procedure. But I don't think that's inherently a bad thing at all. The procedures are effectively version controlled right within your application code, and I'm guessing they're persisted at deploy-time.
- marcosscriven 9y agoBut I thought the headline feature of GraphQL was that the client could choose the shape of the response, hence all those properties. Even then, ten thousand properties seems a huge amount, even for a rich single page app. If you end up putting that on the server anyway, you're back to fixed responses, no better than a REST API.