Closed sedubois closed 5 years ago
I'm hearing more about relay, it's popped up a few times for me recently. is really a replacement for redux? does that mean the whole app structure would change (e.g no more actions/reducers etc)?
@peter-mouland it appears so, instructions to query the data stay together with the view. No more implicit data dependencies across components (but under the hood is one central normalized graph cache). Of course, Relay and Redux could be used together in more complex apps, similar to Facebook which mentions: "One pattern we see emerging is letting Relay manage the bulk of the data flow for an application, but using Flux stores on the side to handle a subset of application state."
Here's an article mentioning one can well stick with Redux, but that doesn't allow to take advantage of some of GraphQL's key benefits.
Conveniently, GitHub just released a GraphQL API, so the example could be updated with it.
Correction, that API isn't public yet, requires agreement to pre-release program then using auth token.
I love GraphQL and Relay, I absolutely agree that they highly likely are the future of APIs.
The issue I have is that it would make react-boilerplate
only feasible for projects that don't have an existing API and/or are willing to make the jump to GraphQL.
I'm willing to bet that that's a pretty small percentage of them, and right now, I'd much rather focus on getting the frontend part 100% right for APIs of any kind and not be tied to any specific backend system.
That being said, I'll happily discuss more about this! Convince me, why should react-boilerplate
switch to a GraphQL/Relay setup by default?
Alright I'll take a chance 😉 I could flip around the argument of jumping to GraphQL: why would new projects, even those already having REST or other APIs, invest in learning and maintaining Redux, Redux-saga, etc, instead of GraphQL/Relay, which seems a more powerful and promising technology?
If we agree GraphQL is the future, shouldn't this boilerplate help projects be part of this future for months and years to come instead of pushing them in the "wrong" direction?
How about providing a minimal GraphQL backend within this boilerplate? Backend devs would have the flexibility to add their own code to plug into existing REST APIs and gradually migrate their code, while frontend devs would have direct access to state of the art DX/UX.
FYI, react starter kit (>10k stars) demoes a GraphQL backend. In choosing between the 2, so far I chose this one for its frontend focus (to balance my primarily backend experience), but I actually saw RBP's state and backend management as weak points. Hence opening this discussion.
Besides the "REST vs. GraphQL" discussion, remember that the choice of GraphQL primarily benefits front-end devs! It enables them to query the data in exactly the way they want it presented, right beside their views, together with static type checking and linting, plus all of the existing and upcoming optimizations. That should support your vision of optimal UX/DX.
I'll have to think about this, it's an interesting direction.
Not convinced this is something we want to do just yet, but I'm now pretty sure it'll happen eventually…
Yes I get you. If you have further thoughts/insights about this or some experiment to share, I'd love to hear back! Also at least when Relay 2 comes out, we should reconsider.
Please correct me if I am wrong, but doesn't GraphQL require the app to have some form of NodeJS (web) server, removing the ability to have the app hosted statically (e.g. CDN)? The ability to just deploy to a CDN (or non-NodeJS server) is one of the reasons that initially brought me to this project.
However, I feel this issue can be mitigated with a proper CLI for RBP that allows one to choose features, i.e. static, SSR/GraphQL, etc.
@mxstbr do you know, off-hand, the Issue/Feature # for the CLI work, if there is one? :-)
However, I feel this issue can be mitigated with a proper CLI for RBP that allows one to choose features, i.e. static, SSR/GraphQL, etc.
I'm not sure this is going to happen in the way you're imagining – I don't really want to maintain multiple codebases at the same time, that's a big pain. (we've been doing that for generator-keystone
and it's the worst)
That being said, the issue number is #180.
I'm not sure this is going to happen in the way you're imagining – I don't really want to maintain multiple codebases at the same time, that's a big pain. (we've been doing that for generator-keystone and it's the worst)
Completely agree-I'd prefer not to maintain separate codebases. I was just trying to think of a way to offer GraphQL and Relay/Apollo in lieu of not wanting to lose the static deployment aspect of RBP. Again, if I'm wrong in the assumption-which was the case last year-that GraphQL requires Node to run, please let me know.
One potentially really cool thing, would be the ability to hot-reload the frontend code upon backend schema changes. It's technically feasible with babel-plugin-react-relay
, but a graphql bug prevents from having it working (npm prune
and npm dedupe
didn't help). Thanks @schickling for troubleshooting!
So right now I first make things work by building the schema manually (by manual call to introspectionQuery
) and passing it to babel-relay-plugin
. Could explore the cool HMR stuff separately.
@jwinn forgot to answer: of course with GraphQL like any other backend, nothing prevents the frontend from querying another endpdoint than an endpoint provided within this repo, and hence ensuring this repo only provides the frontend. I'm curious though, how does this get deployed to a CDN (which I'm not familiar with) as it does have Node.js code (the express server)? And can you give an example of such a CDN/non-NodeJS server?
So the same way it's (from what I understand) already possible to ignore the backend within this repo and query something else instead, it should be possible to do the same with GraphQL.
I'm really looking forward to where this goes 😊
BTW managed to use babel-plugin-react-relay
as documented here: https://github.com/graphcool/babel-plugin-react-relay/pull/11
This opens the possibility of HMRing the frontend upon backend schema changes and having on-the-fly type checking. (NB: don't know what Apollo is capable of to compare.)
@jwinn forgot to answer: of course with GraphQL like any other backend, nothing prevents the frontend from querying another endpdoint than an endpoint provided within this repo, and hence ensuring this repo only provides the frontend. I'm curious though, how does this get deployed to a CDN (which I'm not familiar with) as it does have Node.js code (the express server)? And can you give an example of such a CDN/non-NodeJS server?
RBP does have a NodeJS server (Express) but it's not required. Just npm run build
and copy/deploy the contents of the build
folder over to a CDN, (shared) hosting provider, Apache server, application server, etc. As it's just static content (HTML, JS, CSS, etc.), there is no Node environment required--outside the build process--any web container will do. React, redux(-saga), react-router, etc. do not require a Node backend, so this affords flexibility in how the project is used and deployed.
Correct me if I am wrong (as I haven't checked in over a year), but GraphQL must be run in a Node environment. Under this assumption, switching to GraphQL and Relay/Apollo, in lieu of redux-saga (and reselect), would remove the static deployment--via npm run build
and deploy--ability of the boilerplate. Sure, where static deployment is needed, GraphQL could be removed, but then what would one add for managing the API (e.g. GitHub) interaction and side effects, redux-saga or some other flux-(like) implementation?
Again, I am not inherently opposed to switching. I just want to make sure this concern/consideration is taken into account when determining to overhaul an, arguably, important piece of the boilerplate. :-)
@jwinn as mentioned, the GraphQL client code can access a public API outside of this repo, just like right now it accesses the GitHub public REST API. No intrinsic need for Node.
@sedubois That was the key crux of the assumption. If GraphQL can run entirely client-side, then static deployment is a non-issue. Like I said, the last time I checked (over a year ago) GraphQL required a node environment to work effectively.
@jwinn I think there's a confusion between client and server here. Of course GraphQL clients don't need Node, or they wouldn't be clients.
@sedubois To alleviate any perceived client/server confusion, in this discussion, for all intents and purposes, Relay/Apollo are GraphQL clients, correct?
TL;DR
My concern is related to baking the GraphQL server into the boilerplate. Currently, in the boilerplate, API implementation is left to the developer leveraging the boilerplate. If a GraphQL-based solution can be run (deployed) entirely without NodeJS (outside of the build process), then the concern is no longer valid.
@mxstbr If, from RBP's perspective, the ability to provide deployment of an app into a non-NodeJS web environment, is not required, please let me know.
I am arguing neither for nor against GraphQL, as I think GraphQL can have huge upsides. Also, I feel GraphQL and Relay/Apollo are being conflated here. Neither necessarily, requires the other. Substituting redux-saga(/reselect) for Relay/Apollo should be its own conversation. With another conversation discussing whether a GraphQL server should be a reference implementation on the backend. If there is no intrinsic value of switching to Relay/Apollo, without using a GraphQL server, then, I think, this is where the confusion, if any, in the conversation, is stemming from.
Also, a PR would be appreciated to show how Relay/Apollo (and GraphQL if required) would work in the boilerplate. :-D
If so, what is the value and does the value still exist if GraphQL is not utilized on the backend?
This is a good question, I'd like to know that too.
Can all of this be deployed to a non-NodeJS web environment (e.g. Apache, IIS, Application Server, CDN, etc.)?
As far as I know, there are GraphQL implementations in other languages, but depending on the above answer there might not be a static build anymore like right now.
If, from RBP's perspective, the ability to provide deployment of an app into a non-NodeJS web environment, is not required, please let me know.
I'm not sure. Currently, this is possible because we were always focussed on the frontend side of things. I don't know yet if I want to change that, to be completely honest.
Also, a PR would be appreciated to show how Relay/Apollo (and GraphQL if required) would work in the boilerplate. :-D
I agree, but obviously I don't want anybody to do any "useless" work. (though I would hardly call maintaining a fork of this boilerplate that has Relay/GraphQL baked in useless 😉)
Yes yes, gimme a sec to learn this stuff 😉 something like this: https://github.com/mxstbr/react-boilerplate/pull/1065
I propose to discuss any backend stuff separately, and that could be a non-existent discussion, as PR shows. In the spirit of serverless apps, people could use GraphQL backends-as-a-service which are popping up like graph.cool, reindex.io, scaphold.io, dgraph.com, RethinkDB's horizon.io (OSS; GraphQL coming in next version)?
Relay/Apollo are GraphQL clients, correct?
yes
Can [a GraphQL client webapp] be deployed to a non-NodeJS web environment?
yes
what is the value and does the value still exist if GraphQL is not utilized on the backend?
YMMV but in broad strokes, GraphQL is an improvement upon REST (e.g 1, 2, 3).
If you need to use a REST API, you can wrap it client-side like here. Maybe Apollo's graphql-anywhere
would also be interesting. And this video aims to show that any backend can be converted to GraphQL quickly (in "30 min" 😉).
Ha...thanks for this. After some research I've decided to scrap a bunch of work and start again with Apollo in RBP. It seems like it should be pretty straightforward to drop the Sagas and add in Apollo.
My only concern now is SSR, is it at all feasible with this boilerplate?
@scf4 I think isomorphic-relay
provides that. I'm not very familiar with SSR in general, and I was also wondering, how is SSR provided when deploying on a CDN?
Could you also briefly explain your choice of Apollo as GraphQL client?
You would host all your assets on a CDN, but render the initial HTML on the same server as your API (rather than serving empty HTML on the CDN and waiting to load data from the API server).
I don't know whether Apollo or Relay would be best for React Boilerplate in the future, but since adding Apollo to a project seems trivial (and they're essentially feature-equivelant) it seems to make the most sense for me. It uses Redux under the hood (and can connect to your store) unlike Relay which seems to require a lot of fundamental changes to your stack.
In this PR I added Relay: https://github.com/mxstbr/react-boilerplate/pull/1065 and so far it works...
About CDN, the "problem" is that you don't necessarily have an API server at all. For example right now I experiment with Graph.cool which serves as my only backend. I added a feature request to have SSR in there, who knows.
Apollo seems the better choice in relation to Redux concerns and features. Why would we want to use Relay instead of Apollo?
@alisalaah so far I went with Relay basically for the reasons outlined in the conclusion of this article, but I haven't properly evaluated Apollo myself. That might change when trying to integrate some GraphQL CMS backend such as Relax which is nearing beta. That one provides its own GraphQL client, Relate.
I think the main point right now is to bring attention to GraphQL APIs in general. The choice of GraphQL client in particular to choose on the front-end, or which data/content GraphQL server to have on the back-end, doesn't need to be set in stone. These things would be decoupled.
@alisalaah I tried to integrate Apollo, but encountered issues like 1, 2, 3. E.g there's no data masking, this comment shows it's quite complicated to get fragments working (I just gave up trying), and need to manually handle loading cases. Contrary to what the docs led to believe, I have the feeling Apollo is not so mature and found it easier to integrate Relay (see https://github.com/mxstbr/react-boilerplate/pull/1065) and I even have time travel working as before. Just didn't try sagas (don't want to use them), but I guess should still work as well.
Things I like to happen with RBP
Remember the opinions comes from a person who just learned GraphQL and haven't had an actual experience with it and just knows the benefits.
It seems like Relay 2 may be exactly what we need. I just have no idea when it will be released.
@sourcesoft @scf4 I am indeed curious to get my hands on Relay 2.
Meanwhile (and maybe/probably later too), redux-saga
remains the way to manage state (as in this example visible here that @mxstbr mentioned) and IMHO GraphQL clients could already take care of data fetching, if we demonstrate it mixes well with redux-saga
.
I'm becoming more convinced we should integrate GraphQL and Relay, but still keep Redux and redux-saga for state management and long running transactions. What do you think about that?
Yes sounds good @mxstbr, just need to build a compelling example... Maybe guys you can give feedback on https://github.com/mxstbr/react-boilerplate/pull/1065. Also I experimented with Apollo on top of that: https://github.com/sedubois/belong/compare/gql...apollo but encountered https://github.com/apollostack/react-apollo/issues/267 (also noticed the limitations https://github.com/apollostack/react-apollo/issues/262 and https://github.com/apollostack/react-apollo/issues/268 vs Relay).
What are the reasons to keep redux-saga if Relay handles data fetching?
And how do you feel about the advantages of Apollo listed in this article and the update linked in the first paragraph?
What are the reasons to keep redux-saga if Relay handles data fetching?
I don't use redux-saga
for data fetching reasons. I use it for any sort of asynchronous thing that happens in my application. (which does include data fetching, but with Relay just wouldn't include data fetching anymore)
I believe this is one of the best examples of redux-saga
. There is no data fetching whatsoever happening, it's just an onboarding flow – but it's beautiful to read while your main application stays clean. (imagine all of that being done in the main app somewhere, ugh)
In my mind, sagas are like a separate "thread" of your application. (not a literal thread, just a mental model) You have your main application, and you have another thread for async stuff. (whatever that may be) Those two "threads" only ever communicate via redux actions.
Thanks to react, our main app thread doesn't have to care about anything. It just fires a redux action to say "Hey, something happened" – and then the saga thread may do something with that, or it might not. In any case, sometime later, something happens on the saga thread, so it fires off a redux action to tell the main app thread to do something. (e.g. render something new) Our main app thread stays completely clean and functional, and all the async stuff is delegated to an easy-to-read-and-test saga.
That, for me, is the beauty of sagas, and why I haven't yet switched to GraphQL/Relay – they just can't do that, while data fetching with them is arguably far the better way than AJAX/REST. So let's combine them!
I believe this is one of the best examples of redux-saga. There is no data fetching whatsoever happening, it's just an onboarding flow – but it's beautiful to read while your main application stays clean. (imagine all of that being done in the main app somewhere, ugh)
I believe I can have the same clean syntax using async/await on top of defining custom Promises. But the fact that sagas have take, fork, cancel,... and can build a mindset of dealing with them as a separated thread in a single place makes it unique. IMHO as long as we have Redux, sagas makes life easier.
I think boilerplates like react-starter-kit
are using redux and GraphQL without any Relay or Apolo. It's better to implement GraphQL first and don't ditch Redux yet.
That, for me, is the beauty of sagas, and why I haven't yet switched to GraphQL/Relay – they just can't do that, while data fetching with them is arguably far the better way than AJAX/REST. So let's combine them!
I agree, these (GraphQL and redux-sagas) can co-exist nicely and serve specific roles in an application. For the boilerplate, removing/augmenting the GH REST call with GraphQL (and Relay) would be great to have. Also, GraphQL isn't an "improved" REST, nor is it a ubiquitous replacement. Both have applicable scenarios the other cannot provide. More importantly, the two are not mutually exclusive. Note, I am talking about formal REST, not what some call REST as noted in the FB GraphQL post:
We are interested in the typical attributes of systems that self-identify as REST, rather than systems which are formally REST.
Sorry for off-topic but I couldn't find any contact details for @jwinn. Could you send me a quick email elaborating a bit more about the use cases where you see REST to be superior to GraphQL?
I've integrated Apollo into this repository, to be more precise, a modification of it—without Immutable.js. Everything is in this commit: https://github.com/Dattaya/react-boilerplate-object/commit/47ea450f5744e6cf1f5a88c0d3b03fcc8f4b235e This is what has been done:
graphql.config.json
, maybe some other IDE's support it too. schema.json
from schema.js
—npm run update-schema
Let me know if you want to port some parts of it back into this repo. I would love to get some feedback because I'm also new to GraphQL.
implement GraphQL first and don't ditch Redux yet
Apollo relies on Redux and you can see whatever it is doing in redux-devtools
:
That doesn't mean that I promote Apollo though, I'm just experimenting with different GraphQL clients. BTW, in addition to Relay, Apollo, Relate, and Lokka, there is also Cashay—https://github.com/mattkrick/cashay
@Dattaya looks great! It's nice to see a working RBP + Apollo demo compatible with all the rest. I added some comments on your code, only to be taken into account if you were to submit a PR of course. General message: let's minimize the impact (to ease review and limit risk; things could be removed/added later as needed):
NB: hopefully we'll learn more about the future of GraphQL clients next week after the GraphQL Summit...
@mxstbr what do you think?
Thanks for your thoughts and mentioning Graphcool, @sedubois!
most importantly, graph.cool is not yet in general availability
It will be soon! Additionally, we'll soon roll out support for schema files which allows you to setup a GraphQL backend based on a IDL file like the following (reduced Instagram example):
type Post {
description: String!
imageUrl: String!
comments: [Comment!]!
}
type Comment {
text: String!
post: Post!
}
@sedubois, thank you for your feedback and your comments. @mxstbr wanted to go with Relay and so do I, because it has more contributors and Facebook has more talented developers and resources; it's just Relay 1 is too heavy, 114068 bytes gzipped (React included) and probably too complicated for simple and some medium complexity projects. I hope Relay 2 is better in this regard.
don't remove saga machinery
redux-saga
is there, just didn't want to leave an empty file. As you said, something else should be added to showcase it.
@Dattaya agreed. About sagas I misread the code (e.g when seeing this deleted).
We could either go with Apollo and migrate to Relay 2 when appropriate, or wait for Relay 2. But why wait if Apollo already works well enough? (just thinking out loud here). I also tend to prefer Relay.
+1 for Relay. Reindex too
Since mentioning Graphcool and Reindex I thought I'd chime in with Scaphold.io which has the best free tier and a good API.
On Thu, Oct 20, 2016 at 1:48 AM, Matt notifications@github.com wrote:
+1 for Relay. Reindex too
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mxstbr/react-boilerplate/issues/1041#issuecomment-254905736, or mute the thread https://github.com/notifications/unsubscribe-auth/AAQ9ltissWItUWACIgNRtAg6bagYSkLJks5q1mYOgaJpZM4KGqWr .
We could either go with Apollo and migrate to Relay 2 when appropriate, or wait for Relay 2. But why wait if Apollo already works well enough? (just thinking out loud here). I also tend to prefer Relay.
I'll wait for @mxstbr decision before sending a new pull request. This is how a request to GitHub GraphQL API would probably look like:
query {
repositoryOwner(login: "mxstbr") {
repositories(first: 30) { # Github limits the max value of loaded entries at once to 30
edges {
node {
path
url
issues {
totalCount
}
isFork
parent {
path
url
}
}
}
}
}
}
It gives the following result:
{
"data": {
"repositoryOwner": {
"repositories": {
"edges": [
{
"node": {
"path": "/mxstbr/old-blog",
"url": "https://github.com/mxstbr/old-blog",
"issues": {
"totalCount": 0
},
"isFork": true,
"parent": {
"path": "/poole/lanyon",
"url": "https://github.com/poole/lanyon"
}
}
},
...
Since at least for now you don't want a GraphQL server, it's going to be really easy to migrate to Apollo (I think same true for Relay)—add apollo client and this query, remove data loading with sagas, adjust tests and that's it. Later we can add "load more" button or load more data as the user scrolls.
Facebook's GraphQL appears to me a natural choice of backend protocol for new React projects vs. REST. Within the React ecosystem, it moreover goes nicely with Facebook's Relay, Meteor's Apollo or other client libraries to provide modern UX and DX.
Although it is of course possible to just let the developer call their GraphQL API within a Redux saga, it seems natural to replace Redux with Relay/Apollo/other (also in order to use all current and upcoming features such as caching, optimistic updates, realtime/subscriptions, etc). Apollo actually uses Redux under the hood and documents how to interoperate with an existing Redux store. It means an opinionated restriction of the backend protocol to GraphQL, but that appears in line with the doc: "start your app with our community's current ideas on what represents optimal developer experience, best practice, most efficient tooling and cleanest project structure."
Conveniently, GitHub just released a GraphQL API, so the example could be updated with it.
Is the choice of redux(-saga) set in stone? If not, what do others think of replacing it with Relay/Apollo/other?