 Hi everyone, should I reduce the volume? It's fine. So hi everyone. Welcome back for the last set of the talks So I'm Kiran and I work as a freelancer and I also organize reactors Bangalore I hope most of you here are front-end developers So in my opinion, there are two main areas in front-end one is UI What I mean by UI is How how app looks or how the app behaves right things like Styling, you know animations those sort of things and React does pretty good job with this thing, right? So react is primarily a UI framework and the API and simplicity of react works very well for us So the second important challenge in front-end applications is state management So what I meant by state management is like how we fetch data from the server, how we manage it on the front-end You know, how do we do? How we implement business logic, how we keep our server in sync with the front-end those kind of things So there are quite a few Unfortunately react does support Some sort of state management, but it's not meant solely for that things like contest might help But not for very large applications So there are quite a few libraries like Redux, Mobets and There are quite a few others as well But still even by using these libraries like Redux and Mobets, right? Still we have to Implement a lot of logic on our own, right? Even getting state management right with all these libraries is still hard So this is where GraphQL helps, you know, so GraphQL has much more Structured back-end, right compared to REST, which is kind of you know, not very strict GraphQL has much more structured back-end, right? Especially things like Type system in the GraphQL and features like introspection GraphQL supports These are my two favorite features of GraphQL features like type system and introspection Help us build a lot of tools, right? And which will Help us build better applications with less code, right? Apollo is one such tool which leverages the features of GraphQL and And Apollo is by far the most popular GraphQL client library So GraphQL is something that runs on the server and because of its unique features, right? We can build client-side libraries which leverage the functionality of GraphQL and make our life easy So In this talk, I'll talk more about GraphQL, Apollo and how it helps, right? Even with Apollo, it has, it simplifies, it's much better than Redux or Mobius-based applications But it still has its own challenges and I will explain how to walk on those things Yeah, so in GraphQL or in any Back-end-based applications like we have three concepts, one is queries, mutations and Subscriptions. Queries are used to read data from the server which is equal to get in HTTP and Mutations are to send, to modify data on the server which is equivalent to post with the HTTP and Subscriptions are for real-time updates. So if you are building any real-time applications, you might be using, you might be familiar with sockets, right? So subscriptions are built on top of sockets, right? To provide real-time applications So let's start with queries and see how Apollo helped in this So this is a simple GraphQL query. Here you can see In this query, we are asking for users with And within users, we want properties like ID and first name, right? So this is a typical GraphQL query So GraphQL is quite different from the REST in the sense in the GraphQL Clients ask for what they need. In REST, we just hit an endpoint and we get the data back But in GraphQL, the client's request for what properties it need. For example, the user's database might have like 10 more properties But the server doesn't return those properties. The server returns just the users with ID and first name because that's what GraphQL client asks for. So this is a simple GraphQL query and to use it in our Applications, we can wrap this with GQL. So GQL is a helper function Which takes a string GraphQL query and converts into a JavaScript object, which we can use it Apollo or any other library So how can we use this query and fetch data from the server and pass it to our components? So there are a couple of ways and So using higher-order component is one way. So we can import GraphQL from React Apollo and UserList is a simple React component which just renders which gets a list of users and renders the Users and it's a user list is simple React component and We use a higher-order component called GraphQL and we will wrap our user list component with GraphQL higher-order component and pass user query Pass user query Right and so this is the only line of logic We have to write and Apollo takes care of the rest of the things Apollo makes a API call to the server gets the data and Pass it to the server Like if you are doing the same with Redux or anything So you have to implement using some sort of at your surface You have to make an API call get the response, you know implement You know error handling and you know storing the data in the cache so on so forth Right. So those things we need not do with Apollo. So like Because of the previous step, you know In addition to giving getting the fetching the data from the server and passing it to our components We also get loading state and errors, right? And So for example, while the request is happening the loading will be true So if you want to show some spinners or something we can do that or if the request fails you know, we get a rest we can handle the errors as well and if the Request is successful will get the users data and we can use that to render the company, right? So you can see that, you know without writing much code, right? We were able to get data from the server and you know use it You know, we are not writing any additional code for you know managing the loading state or handling errors Are fetching the data, you know Apollo is taking care of that Automatically all we have to do is write a GraphQL query and wrap our React components with GraphQL queries and Apollo also caches the data in the sense, you know once Apollo makes a request and it stores in the cache and When we render the same component again, Apollo doesn't send the same request again, right? And so we need not implement that kind of logical So Apollo takes care of itself and Apollo stores the data very efficiently for example Let's say when we when we fetch when we made a request for the users we got two user objects, right and it is storing it with reference to user one and user two, right and It shows that user one and user two objects separately so that you know if some other queries Faches the same data, you know, we need not duplicate data. So this is called data normalization, right? So it stores efficiently and avoid any data duplication also if because of some other Query if one of these objects are modified, you know, the data will be sink across all the components So there won't be any data inconsistencies So if your application is read heavy for example, if you are working on some media applications or some content based applications where you read different sort of data and render it on applications then GraphQL and Apollo works great So as you can see we haven't written much code, right? We are writing queries and you know Wrapping our components with that. So if you if you are building dashboards or if you are building content based applications, you know This fits very well So the next part is the mutations where you know, we are making edits and you know sending So some of the applications where mutations will be heavily used is some sort of CRM based applications where you know User enters data and the data is saved into the backend applications So let's see how you know Apollo fares with this So to send uh data to make changes to the server, right? Again, we write queries These are called mutation queries in this case. We are writing update user And to this update user field. We are passing arguments, right? So GraphQL query language is quite extensive in the sense, you know, it has augments. It has variables You know, it's quite extensive. So in this case, we are using um variables like like augments like id and first name and In response, we are we want to mutate the server with id one and first name first name is called johnny And once this mutation is once the server got updated, we want to get the response back In the response, we want id and first name ideally the data will be the same so This is a typical mutation Query Or as you can see in this query, we hard-quoted, you know, id and first name But in real applications, we don't want to do that, right? So we want to use some sort of parameterization So for that, we can use uh things like GraphQL variables in the sense, you know, we have one more layer where, you know, after mutation we can give an operation name And in the operation name, right, we can specify the Augment types in the sense, for example, we can say id is of type int And first name is of type string, right? So GraphQL is a strongly typed long ways So whether it is getting data from the server or, you know, specifying the augments, you know, it takes care of You know, it takes uh types very seriously Right. So this query is almost same as the before except that in this case instead of hard-quoting the id and first name We are using parameters So the how how can we call that query? There are several ways to do that. So this is one of my favorite way where we will Directly call mutate on the client, right? So how how we get this Apollo client? It's doing the setup page. Uh, we will uh Use the Apollo client library and, you know, give the cache and so on so forth augments And finally we'll get a client library Apollo client and that we can directly call mutate and for that we can pass the mutation Which is a query which we wrote earlier and pass the variables So these variables will be passed to the query and it will be evaluated on the server And once this mutation is executed We get the response from the server in some sort of dispassion like we get the data inside that we have update user Because the mutation field which we sent is update user So in the response object also we get the update user and inside that we have id first name Right because that's what we ask for and in addition to that we have underscore underscore type name As you can see in my previous cache diagram, right? So apollo is storing with as references like user one, right? So so these Cache keys are very important because whenever Apollo sees some response from the server and if it finds underscore underscore type name and id Right it immediately maps with the cache and updates it So we need not write any code in the sense, you know We got some response from the graphical server apollo automatically understands that okay This data should be updated at that particular location and updates it. Right? We need not write any logic so again, uh, this is very helpful and It also supports something called optimistic response. Let's say for example, if you are implementing Chart application and you entered something, right? You want to see that message immediately even before that message Went to server and come back, right? It takes some few milliseconds before even getting response from the server We want to show that response immediately for that. We can use this optimistic response In most of the cases we know how the response for example when we are sending a message, we know What the message will be right even before coming from the server So we can give you a mock response Based on our assumption in this case, you know, for example update user We are sending id and first name, but that's the same response. We are going to get back So we can give you a mock response as an optimistic response So what apollo does with this thing is it renders the react components twice Once before getting the response from the server and once after getting the response from the server So that where that's where you see the instant response in the sense, you know You type some you enter something you immediately see the response You made it before even before getting the response from the server and once the actual response comes Comes from the server, you know apollo re-renders again and you know Does it correctly? So this gives you know pursued better performance As you can see it looks good in the sense, you know, we are not writing any additional logic to update cache or anything But still it seems quite a verbose, right? All we want to do is update first name, but for that we have to write a query and you know We have to call that mutation function. So it it seems verbose, right? What if we have a function like update record, right? And for that we'll say I want to update record for the type name user and id one And this is the data I want to save it to the database And this update record method can be used for n number of fields. For example, your application might be Having like the three tables and you can use this method to update any Uh any table and any property, right? So, uh, we can do that, you know, apollo doesn't provide this method, but we can implement our own on our own, right? We can write a generic function, right? We can use this three information like type name id and data And generate the query the query, which I have mentioned before, right? Which essentially contains this information, right? We can take this information Write a function which generates that query automatically, right? And call the mutate function So with the with the help of that function We can have a cleaner API like this instead of writing the mutation query for every single update We'll write a generic function and use that function everywhere Right? So this reduces the boilerplate code So far we are looking at the good parts of the apollo, right? So we have seen how fetching the data from the server with apollo is very easy And you know how it provides loading status errors, you know, how it's providing cash Right and how we can handle updates Uh, we have discussed that, you know, uh, updating is slightly verbose But it's handling the cash well, but it's slightly verbose But we were easily able to write a simple function called update record and remove that verbosity So the so far we are good with apollo So these are the hard parts of apollo, you know, creating and deleting objects and you know, subscriptions So these two things require a lot more effort than the previous cases I'll explain why this requires more effort Let's say you want to delete a user, right? And again, you write a mutation query called delete user and you pass an augment called id So you want to delete user number one, right? And in return, you just get an id, right? But apollo don't know what to do with that, you know We send a mutation to delete user and you got the id back What should apollo do with that? But in previous case, you know update it can update the cash But in the delete case that Particular object might be referred from several other places, right? So apollo can't Guess where it has to delete So it's our responsibility to give us more guidance So this way things get complex in the sense, you know, in addition to the passing the mutation and variables, right? We have to write implement a method called update, right? And in this update have three steps like first Again, apollo cash Stores the data in a separate format. We can't directly read the data, right? The only way to read the cash is reading the query. So to read the cash will pass a query, right? And We'll use cash that read query and pass a query and we get the users data And we want to delete a user, right? So we'll filter, we'll run, we'll iterate over the users and delete the user which we don't want Now we get new set of users and we'll write it back Right, so we have three steps And this is a simple case, right Things can get complex let's say you have A role-based application where, you know, you have users who have who have Rows like admin super user and user, right? And we have different queries To get this data the moment you use you delete a user You have to update these queries as well So the previous query the previous logic which I have shown is for one one query Let's say you have to Implement the same logic for three more queries, right? So you can see it's already 20 lines of code and it it can be A hard tedious and it can be error prone as well. For example, let's say Someone else is adding a new feature, right and they added a new query They might get they might forgot to add update method in the world features, right? And it cause a lot of problems and inconsistencies so manually implementing The other way of doing instead of implementing the update method is refetching all the queries, right? Again manually specifying which queries to refetch is also tedious and it has the same problems as this right So can we automate it right instead of manually implementing the update method which we have seen is quite verbose can we automate it So again previously I have shown an update record method where we are passing type name id and data and that API looks good, right? and Can we have the similar API for this when I want to delete some some particular object All I want to call is like call some function like delete record Pass the type name and id that's all I want to do, right? So the rest of the logic should be taken care by the delete record method But Apollo doesn't provide it can we implement on on our one so If we if we can find out all the queries which are related to user So I'll show you a demo so You can see here, right? currently there are two users right and when when I add a new user right and I assign a role as admin you can see The the moment I add a role as admin here this list got updated and if I go ahead here And change the role to user you can see this this particular section of the UI got updated right and if I delete something Right, you can see that you know the user from this section got deleted. So the the UI is interlink And to implement this we have like four queries One query is to fetch the users from the server and we have three queries here One query is to get the list of admin users one query is to get the list of super users and one query is to get the list of users right, so How can we do that? As we discussed so till now like doing that manually manually specifying the update method are manually specifying which queries to refresh Is tds and error prone. So how can we do that automatically? So we wake today morning and discuss the word ast, right? So we can use some tools like ast traversal traversal and graphical schema introspection right we these are the Some of the features of the graphical and we can use these to automatically identify which queries need to be automatically updated So So this is a simple graphical query, right? So the entire query is called a document right and inside if you see whenever you see a curly braces, it's called a selection set right Anything within the curly braces is called list of selections And the first one is called the field again. It goes on. So it has a predictable structure, right? And this is very basic query the ast of that particular simple query Look something like this. It looks daunting, but it has very predictable structure. So that's what that's what ast is for right, it takes the ast is Takes the human readable code and converts into a much more complex structure But these complex structures are friendly for programming, right? So today morning we have seen how we have described how we can use the ast is to write babel plugins and yes lint plugins The same concept applies here As you can see for the previous queries, we have selection set inside that we have selections inside that we have field called users, right? so So the next part is like schema introspection, right? so So this is the query which can you which can be used to get the data related to the schema, right? And so in this case, you know We can get the list of the fields and the the types of those fields, right? We can combine these two things to automatically find the queries which are which are related to users And in addition to that apollo tracks all the queries in the app, for example As you are using the app apollo keeps fetching the data from the server and it also tracks those queries which it has already executed so apollo has a list of the watched queries and Let's say you want to delete an user So from the list of all the queries, we have to filter out the queries related to the user, right? So we can use the ast concept iterate all the queries find the queries which has field users, right? If we have any confusion related to the type of the fields, we can use the result from the introspection Once we have the list of queries related to the user, we can implement a generic update method, right? We can iterate all the those queries and implement the three-step process which we have done read the cache Do the whatever modifications we have to do and write it back, right? We can automate it The challenging part is finding the queries related to user for that we can use the ast and introspection So the same the same problem happens for create also, right when we're creating, right? It will have some side effects, right? Those those things also should be updated for that also we can implement the same logic similar to delete record So the next part is subscriptions Subscriptions is a little bit hard to implement Subscriptions are used for real-time updates It it has like a lot of moving parts like you know Whenever you change something on the server with mutations If you want to implement subscriptions, we have to publish those changes Like let's say you added in user, you publish that, right? And you have to implement a subscription resolver in the in that resolver implement Authorization so on so forth, right? On the front end, you'll write a subscription query, right? And again, this subscription has the same challenges which I described for the delete and update, right? This subscription will get the real-time updates from the server But once it gets the real-time updates from the server, Apollo don't know what to do it If a new user got added, what should Apollo do? It doesn't know, right? So here also the challenge of you know, implementing the update method happens But you know we can we can use some of the methods which we have developed But still it's verbose, right? And it requires a lot of effort to implement these subscriptions And you know it also causes performance for example in our application We have 33 tables and for each table we have three subscriptions One for delete one for update and one for creating a new item Like if you have 90 subscriptions, the performance of the app will grow high The more than number of subscriptions we have, the bad the performance of the app will be Right? So there's an alternate proposal called live queries, right? So the idea with the live queries is we have a regular graphical query And we'll mark that as an iterate live, right? So without implementing any logic, the library which we are using Should take care of keeping this data in sync with the server If something changes on the server, client should automatically get updated Right? Without writing any code That's the idea or algae So this is still in the proposal phase, which is not yet confirmed Or there are no implementations available But in our applications we had to implement it on our own Because you know we have a big application And subscriptions are not working out for us So we went ahead and you know started implementing our own live query system So the implementation will look something like this You know whenever the clients are querying the data from the server We wrote an extension which keeps track of all the objects which are sent to the clients We'll store that in the send redis When the clients are sending the mutations We'll use database trigger to identify those changes that are happening So we'll use this to information like the objects which are stored in the redis And the triggers And based on this we will write an efficient subscription Single subscription to keep the data in sync So the beauty of this architecture is We have decoupled our data-syncing logic from our business logic So it's kind of a one-time effort We'll implement just a single subscription Instead of having like hundreds of subscriptions We'll have a single very generic subscription called onchange Which will get the data action This action could be either an update, delete or create So it can be one of these three actions And data is the actual data which is changing And type name and ID So with this just single subscription We can keep our entire front end in sync with the back end Again Yeah So Apollo is mostly good Things like mutations and subscriptions are a little bit hard But we welcome them with implementing our own systems Like update record and live queries Yeah So that's all I have So if you have any questions you can reach out to me at kirana-buri Do you have any time for questions? Okay