I tried 3 times to get comfortable with GraphQL and I just gave up in the end. The query language may look simple but it becomes this behemoth of code, get comfortable with scrolling. Plus having to define the mutation & query for each is a pain and I just gave up. To clarify Jack's comment on GraphQL letting anything through, thats not exactly true, as behind the scene, your query is run and if its not expecting an query param, it wont process...
@@mubashir3 obviously the syntactic sugar you use to make sure you transpile to ECMAScript 5 before you ship is needed to think it's worth, and maybe make you feel good on thinking you are smart 🤓 I love sarcasm btw
I think it's also worth mentioning, there's still at least one thing that REST APIs are good at: Building APIs that third-party developers can integrate with. As long as you have a REST API any developer outside your team or company will be able to integrate with your infrastructure. With REST APIs, all they will need is an HTTP client and some documentation.
@@impregnat0r I wasn't talking about things which can 'interact' with it but about beckend and languages and tech where you can utilize it. If you wrote your backend in Go, you won't / can't use trpc to send data between SPA and your (Go, C# etc) beckend.
Thanks Jack! These days, decisions are getting even tougher. Add tanstack query / table to the mix, and everything compounds further (i.e. where to use client side, where to use server side granularly). Oh the horror. I gave up on graphql, and trpc due to the lack of ease of use. Server actions FTW!
graphql queries should be two arrows up, because you literally can build what you want in the request itself.. unlike REST where this filtering logic you gotta do yourself
Even when I use next/svelte, I create my API endpoints then if need be I use server actions in forms etc... But those actions just contact the API. For me it is just a nice thing to have for the front. I like svelte more because backend fetch on your own api does not actually trigger a network request it makes a function call
REST also works without JS..., that's the whole point of stuff like htmx and go, but this can be achieved with regular html.... a form is designed to make a post request when submitted to an endpoint, that's why you see a lot of "preventDefault" when using a library, because most of the time you want to do JS stuff before fetching.
Maybe I'm misunderstanding, but the only way different clients such as desktop or mobile apps can get consume data from a server is through an API that returns JSON. You can't do that with server actions or returning html unless you're scraping the data, but who does that? Am I correct or am I wrong? Is there something that I'm missingm
@@PS-dp8yg well the response and request are separate things. If you are returning html, then you would not use it anywhere else, except the browser. You could return different things depending on the client, but that is not necessary efficient. Now we have this new standard called htmx which is all about returning html. Supposedly you can code without using javascript, except it is used for back-filling in older browsers.
@@breakablec Thanks for the response. I know that that response and request are two different things. The whole idea of returning JSON is to build multiple clients that consumes the same data. If the data changes, then all clients will have that change. If you need multiple different clients, it would be no problem. Once you start using Next.js and return react components, you are stuck with Next.js and React. If you return only HTML, you are stuck with building any platform that supports HTML(browser). Of course, you can have Next.js that returns react components, and at the same time, create and API endpoint for other clients. I heard of htmx and it seems promising, but we need to see how it will do against large applications.
I can disagree GraphQL is more type-safe than tRPC if we are talking about typescript on both client and the server. tRPC uses the same types you define on the backend, so it should always be type-safe. GraphQL however needs code generation always, so things could go wrong and on top of that, it does not have the concept of null vs undefined, which can also prove to be very problematic in some occasions.
Could not just do a rest request with a form post and then progressively enhance if you have JS to fetch (giving rest an up arrow in "works without JS") ?
tRPC 11 is in the works, and I'm working on some transport layer features. Could you offer any specific feedback on improving Ease of Use, mutations, or queries? Also, I really am scratching my head about the type safety category... what would earn 3 green arrows? 😂
Awesome, and again, just my opinions on these. I gave GraphQL three arrows because any client can get the server schema and then build it's own types and query/mutation wrappers from there. AFAIK, tRPC doesn't have that language independent representation of the RPC API and its types.
@jherr It's not a primary feature, that's for sure. Idk about feasability, but it's possible to generate an OpenAPI Spec from your router def and from that, generate language-specific clients. Since the zod validation is all server side, you still get the runtime type-safety, but it's maybe not as a great a frontend DX 😅 Aww man, it's a brainworm, now. I'm going to have to ask my 🦀 friend to try it in Rust... But yeah, you only get a well-defined API with tRPC and GQL.
Great content as always. But for me, the complexity of the app to build is a key factor in deciding which method to use. Personally, I don't believe in Server Actions for enterprise-grade applications. The code base is spaghetti code with no seperation of concerns. Same goes for TRPC, which is a little bit nicer but still lacks flexibility for modeling complex business domain interactions.
Could you expand on 'tRPC lacks flexibility for modeling complex business domains'? Can you give an example of a limitation you've encountered? Genuinely curious!
@@Alec.Vision For me at least 3 reason why I personally don't use tRPC. First it works the best with monorepo and fullstrack framework as nextjs. Second the compatibility between tRPC and the latest releases for other packages or framework. Last it works only with Typescript. But what if a piece of the backend is using python for some IA functionalities. If I use tRPC in my code base I can see clearly what I will loose and the "package lock" that I will have, but I cannot see really the benefits. If it is only type safety, I can achieve it easily but just coping my types.ts file between my front end and backend and use RTK Query or React Query which will bring even more value than just type safety. Also I am big fun of Zod I use it a lot for my forms validations and for database queries but I don't think is suitable for API validation. I prefer using class validator for this part.
I thought about putting it on here, but it doesn't natively sit on top of HTTP, and so I think it's uncommon at the FE level. You can do the proxy thing. It's just hard to compare that with these more common solutions.
What about client cache? i never ised server actions. with tRPC you have react-query cache and with GrapthQL all clients have cache. In rest you can use react-query as client cache
Who would disabled JS ? That doesn’t matter. It looks to me from this comparison that tRPC is more versatile so it should be consider a standard approach.
About DoS in GraphQL, why not rate limit in graphql context? Rate limiting using url is REST’s thing. So, no wonder REST is good and Graphql is bad in this context But I think graphql can calculate query operational cost in their server. So why not let they do the stuff?
Rate limiting and query cost are fantastic B2B. But if it's B2C then are you going to charge your customer directly? Or rate limit their eCommerce session? The only thing I've seen work there is to white list specific queries, which ends up defeating the value of GraphQL in the first place.
Surely tRPC is as type.safe ass GraphQL? Also the fact server actions need forms to use is kind of annoying. GraphQL is overkill for most apps I think and the amount of codegen was uncomfortable
What tRPC lacks is the self identifying schema which allows any client in any language to create type safe bindings right out of the box. You may not need that, but it does distinguish GraphQL in terms of type safety.
@@jherr yeah the fact that tRPC can't be consumed by external services easily is a downside for sure. For our own software we use monorepos to solve this issue but when other 3rd parties we have to use the OpenAPII adapter to allow it to be consumed just like a normal REST API with a generated swagger page to at least provide some kind of schema to use (granted with the lack of type safety you pointed out for REST).
That's why it's a mix of a score. It can be really great and flexible BUT you have to be cognisant of a significant downside. Which, given some of the comments, folks are unaware of.
By all means use server components. But server actions? Thats a big no from me as i prefer my separation of concerns lol Especially as your codebase or project gets bigger lol it will become much much harder to maintain
Graphql is a steaming pile of doggy doo for a plethora of reasons. Also, you can't really compare Graphql or query apis to REST, as REST is a protocol. It's like comparing apples to bananas.
HTTP is the protocol. REST sits on top of HTTP and is an "architectural style" that covers the actions you can take on the entity or entities using HTTP verbs.
@@Dylan_thebrand_slayer_Mulveiny It's common for developers to say that any w use fetch to get data we are "making a REST request". That's not the case. Fetch is a replacement for XMLHttpRequest. Note "http". fetch makes http requests of all types, including JSON and XML, but also HTML, images, etc. fetch makes HTTP requests. REST is a specific "architectural style" that loosely defines entities as a hierarchy, referential data that should exist in the return body, and it recommends the meaning of HTTP verbs. en.wikipedia.org/wiki/REST#Applied_to_web_services When the REST paper was published (which came well after the releases of IE and Netscape Navigator that supported client-side XML requests (with different APIs of course)) it was a lightweight response to SOAP. SOAP was a very specific protocol where both requests and responses could be validated to conform to the protocol. REST was much less strict (and easier to use), but you couldn't make a universal REST client because there was no set protocol to validate against. The whole appeal of REST is that it wasn't a protocol like SOAP. You didn't need to adopt most of the recommendations. IIS at the time couldn't respond to anything other than GET/POST, so Microsoft REST APIs didn't use the verbs. A bug in a version of Flash player meant that it would only handle 200 responses, so we stopped using error codes and instead encoded error responses as 200s (sigh, a mistake we are still paying for today.) From the jump the abstraction of REST leaked terribly. If you do /[customer]/[orders] and /[products] how do you get all the orders for a particular product without duplicating orders under products (a REST no-no). So 100% of all "REST" services I've worked with have always had an adjunct RPC API to handle the leaks. That leakage and need for reporting in a uniform protocol was what gave us GraphQL. And GraphQL is a protocol where requests and responses can be validated to the point where we can build clients that are guaranteed to work based on that protocol. So no, REST is not a protocol, and that's by design. GraphQL, gRPC, HTTP, FTP, TCP/IP, those are well structured communications protocols.
I think you were a bit unfair to Graphql. People hitting your API is not a concern, I'm not sure where you got that information. Queries and mutations should be at minimum 2 up arrows, maybe 3, because you can define exactly what you want, quite easily.
wundergraph.com/blog/graphql_is_not_meant_to_be_exposed_over_the_internet#do-you-fully-understand-the-risks "GraphQL on the other hand, a single Query might result in thousands of calls on the controllers (resolvers) of the API. There is no simple way to solve this problem." We ran into the issue at a major eCommerce company where we deployed end-user facing GQL with open requests and the API got frequently attacked and it was impossible to tell valid requests from malicious requests at the edge becauase the query was in the payload. We ended up going to white-listed query which defeats the purpose of GQL in the first place. The query complexity issue is the reason why B2B GQL APIs have per-query cost calculations.
love tRPC so far but saying it would be "easy to setup", for me as a beginner at least, is a LIE. I actually watched your nextjs trpc tutorial and you didn‘t even cover everything. The tRPC docs are ok at explaining the concepts but it wasn't fully clear for me, others do a better job. Maybe more examples might help. Ofc using t3 helps but I wanted to integrate it into an existing project edit: also you need to be familiar with tanstack query to really utilize tRPC
Actually, REST is not a standard, it's an "architectural style", which is why you'll never see a one size fits all REST client that doesn't have a ton of configuration options.
@@akrishnadevotee Yeah, ok, that's fair. I just find it frustrating when folks call it a standard because I've never worked with a pure "REST" interface that didn't leak. They always need a non-standard set of RPCs for reports, multi-table inserts, etc..
I tried 3 times to get comfortable with GraphQL and I just gave up in the end. The query language may look simple but it becomes this behemoth of code, get comfortable with scrolling. Plus having to define the mutation & query for each is a pain and I just gave up. To clarify Jack's comment on GraphQL letting anything through, thats not exactly true, as behind the scene, your query is run and if its not expecting an query param, it wont process...
I always stick to rest, all those years and still that relevant
You'd be happy to know that ECMAScript 2 from 1998 still works. No need to learn new stuff.
@@mubashir3 obviously the syntactic sugar you use to make sure you transpile to ECMAScript 5 before you ship is needed to think it's worth, and maybe make you feel good on thinking you are smart 🤓 I love sarcasm btw
I think it's also worth mentioning, there's still at least one thing that REST APIs are good at: Building APIs that third-party developers can integrate with.
As long as you have a REST API any developer outside your team or company will be able to integrate with your infrastructure. With REST APIs, all they will need is an HTTP client and some documentation.
this is still the case even if you use Trpc tho - just give them the endpoints
@@chance2480 You mean if you're writing your API backend in TS? From my experience, most backend/Web API developers don't use JS/TS.
@@impregnat0r it's for JS/TS endpoints
@@impregnat0r I wasn't talking about things which can 'interact' with it but about beckend and languages and tech where you can utilize it. If you wrote your backend in Go, you won't / can't use trpc to send data between SPA and your (Go, C# etc) beckend.
Thanks Jack! These days, decisions are getting even tougher. Add tanstack query / table to the mix, and everything compounds further (i.e. where to use client side, where to use server side granularly). Oh the horror. I gave up on graphql, and trpc due to the lack of ease of use. Server actions FTW!
REST is the most well-known and commun, all tutorials start with REST. % of usage and popularity could be good criteria too.
graphql queries should be two arrows up, because you literally can build what you want in the request itself.. unlike REST where this filtering logic you gotta do yourself
Even when I use next/svelte, I create my API endpoints then if need be I use server actions in forms etc... But those actions just contact the API. For me it is just a nice thing to have for the front. I like svelte more because backend fetch on your own api does not actually trigger a network request it makes a function call
Haha. One of my favorite thumbnails yet. 🤣
REST also works without JS..., that's the whole point of stuff like htmx and go, but this can be achieved with regular html....
a form is designed to make a post request when submitted to an endpoint, that's why you see a lot of "preventDefault" when using a library, because most of the time you want to do JS stuff before fetching.
Thank you. Happy holidays!
great video , thanks Jack
You can certainly do form requests with rest it is just a matter of how you encode it
Maybe I'm misunderstanding, but the only way different clients such as desktop or mobile apps can get consume data from a server is through an API that returns JSON. You can't do that with server actions or returning html unless you're scraping the data, but who does that? Am I correct or am I wrong? Is there something that I'm missingm
@@PS-dp8yg if you do not have javascript then the only way to respond and show data is by responding in html either for the whole page or an
@@PS-dp8yg well the response and request are separate things. If you are returning html, then you would not use it anywhere else, except the browser. You could return different things depending on the client, but that is not necessary efficient. Now we have this new standard called htmx which is all about returning html. Supposedly you can code without using javascript, except it is used for back-filling in older browsers.
@@breakablec Thanks for the response. I know that that response and request are two different things. The whole idea of returning JSON is to build multiple clients that consumes the same data. If the data changes, then all clients will have that change. If you need multiple different clients, it would be no problem. Once you start using Next.js and return react components, you are stuck with Next.js and React. If you return only HTML, you are stuck with building any platform that supports HTML(browser). Of course, you can have Next.js that returns react components, and at the same time, create and API endpoint for other clients. I heard of htmx and it seems promising, but we need to see how it will do against large applications.
Hello, can tRPC works with Golang as the server and Next.js ate client ? is there any example ?
I can disagree GraphQL is more type-safe than tRPC if we are talking about typescript on both client and the server. tRPC uses the same types you define on the backend, so it should always be type-safe. GraphQL however needs code generation always, so things could go wrong and on top of that, it does not have the concept of null vs undefined, which can also prove to be very problematic in some occasions.
great video, thanks
Could not just do a rest request with a form post and then progressively enhance if you have JS to fetch (giving rest an up arrow in "works without JS") ?
You could use a form post for a subset of REST (GET and POST).
tRPC 11 is in the works, and I'm working on some transport layer features. Could you offer any specific feedback on improving Ease of Use, mutations, or queries? Also, I really am scratching my head about the type safety category... what would earn 3 green arrows? 😂
Awesome, and again, just my opinions on these. I gave GraphQL three arrows because any client can get the server schema and then build it's own types and query/mutation wrappers from there. AFAIK, tRPC doesn't have that language independent representation of the RPC API and its types.
@jherr It's not a primary feature, that's for sure. Idk about feasability, but it's possible to generate an OpenAPI Spec from your router def and from that, generate language-specific clients. Since the zod validation is all server side, you still get the runtime type-safety, but it's maybe not as a great a frontend DX 😅
Aww man, it's a brainworm, now. I'm going to have to ask my 🦀 friend to try it in Rust...
But yeah, you only get a well-defined API with tRPC and GQL.
@@Alec.Vision Cool, so, possible, but not out of the box and easy. I'll be excited to see if that happens for tRPC.
Hi sir , totally out of context question, may I please know if Micro frontend and module federation is compatible with next 14
Great content as always. But for me, the complexity of the app to build is a key factor in deciding which method to use. Personally, I don't believe in Server Actions for enterprise-grade applications. The code base is spaghetti code with no seperation of concerns. Same goes for TRPC, which is a little bit nicer but still lacks flexibility for modeling complex business domain interactions.
Could you expand on 'tRPC lacks flexibility for modeling complex business domains'? Can you give an example of a limitation you've encountered? Genuinely curious!
@@Alec.Vision For me at least 3 reason why I personally don't use tRPC. First it works the best with monorepo and fullstrack framework as nextjs. Second the compatibility between tRPC and the latest releases for other packages or framework. Last it works only with Typescript. But what if a piece of the backend is using python for some IA functionalities. If I use tRPC in my code base I can see clearly what I will loose and the "package lock" that I will have, but I cannot see really the benefits. If it is only type safety, I can achieve it easily but just coping my types.ts file between my front end and backend and use RTK Query or React Query which will bring even more value than just type safety. Also I am big fun of Zod I use it a lot for my forms validations and for database queries but I don't think is suitable for API validation. I prefer using class validator for this part.
HI JACK, I want to build a web using Next.js 14, and a mobile application using Flutter, what is your recommendation to use?
TRPC. It’s easy and consistent. The typescript won’t help you with dart, but it’s not worse than rest in that regard.
Thanks, When your NextJs pro be launched?@@jherr
How would you compare gRPC to these three? I think it's similar to the tRPC column, but also works outside of JS/TS.
I thought about putting it on here, but it doesn't natively sit on top of HTTP, and so I think it's uncommon at the FE level. You can do the proxy thing. It's just hard to compare that with these more common solutions.
What about client cache? i never ised server actions. with tRPC you have react-query cache and with GrapthQL all clients have cache. In rest you can use react-query as client cache
You'd have to cache it yourself. It's primarily meant as a mutation mechanism, not a query mechanism, so consider it like you would a POST HTTP fetch.
does making an api request to the backend REST API inside server action make the mutation slow...??, I mean what do you think about that...??
it would make it as slow as the response time of the backend service, plus a small overhead. on the client it's a non-blocking promise.
Who would disabled JS ? That doesn’t matter. It looks to me from this comparison that tRPC is more versatile so it should be consider a standard approach.
What are server actions? any cues in the video mb, links?
nextjs.org/docs/app/api-reference/functions/server-actions
About DoS in GraphQL, why not rate limit in graphql context?
Rate limiting using url is REST’s thing.
So, no wonder REST is good and Graphql is bad in this context
But I think graphql can calculate query operational cost in their server.
So why not let they do the stuff?
Rate limiting and query cost are fantastic B2B. But if it's B2C then are you going to charge your customer directly? Or rate limit their eCommerce session? The only thing I've seen work there is to white list specific queries, which ends up defeating the value of GraphQL in the first place.
Surely tRPC is as type.safe ass GraphQL? Also the fact server actions need forms to use is kind of annoying. GraphQL is overkill for most apps I think and the amount of codegen was uncomfortable
What tRPC lacks is the self identifying schema which allows any client in any language to create type safe bindings right out of the box. You may not need that, but it does distinguish GraphQL in terms of type safety.
@@jherr yeah the fact that tRPC can't be consumed by external services easily is a downside for sure. For our own software we use monorepos to solve this issue but when other 3rd parties we have to use the OpenAPII adapter to allow it to be consumed just like a normal REST API with a generated swagger page to at least provide some kind of schema to use (granted with the lack of type safety you pointed out for REST).
@@tom.watkins From an external source perspective it's no better or worse than just plain REST.
is form action the only way to use server function in server component?
you can create form actions through JS, so I would say no.
hey jack, im working on a project that have a c# backend and how can i use trpc
Yep. Glad you mentioned that since folks seem to think you can’t use tRPC with typescript.
@@jherrhey jack, i was actually asking you how to use trpc with c# backend
@@dgcp354 oh, yeah, i don't know. the types are driven by the server.
I was just thinking about you. Hope all is well.
All is well. Thanks!
Trpc: Querying
Seerver Actions: Mutations
There are plenty of ways to secure a graphql api. Persisted queries for example, so I wouldn't use that as an argument against GraphQL.
That's why it's a mix of a score. It can be really great and flexible BUT you have to be cognisant of a significant downside. Which, given some of the comments, folks are unaware of.
The works without JS argument to me it's so dumb
REST will outlive all these fads, so there's that.
By all means use server components. But server actions? Thats a big no from me as i prefer my separation of concerns lol
Especially as your codebase or project gets bigger lol it will become much much harder to maintain
The server action can still call microservices on the backend.
This video fails in for whom the rating is for - caller vs reciever. Seams like it for consumer perspective (and JS).
Graphql is a steaming pile of doggy doo for a plethora of reasons. Also, you can't really compare Graphql or query apis to REST, as REST is a protocol. It's like comparing apples to bananas.
HTTP is the protocol. REST sits on top of HTTP and is an "architectural style" that covers the actions you can take on the entity or entities using HTTP verbs.
@@jherrIt's an abstraction of HTTP, but it's still a protocol. It responds to requests with data, the same as HTTP does.
@@Dylan_thebrand_slayer_Mulveiny It's common for developers to say that any w use fetch to get data we are "making a REST request". That's not the case. Fetch is a replacement for XMLHttpRequest. Note "http". fetch makes http requests of all types, including JSON and XML, but also HTML, images, etc. fetch makes HTTP requests.
REST is a specific "architectural style" that loosely defines entities as a hierarchy, referential data that should exist in the return body, and it recommends the meaning of HTTP verbs. en.wikipedia.org/wiki/REST#Applied_to_web_services
When the REST paper was published (which came well after the releases of IE and Netscape Navigator that supported client-side XML requests (with different APIs of course)) it was a lightweight response to SOAP. SOAP was a very specific protocol where both requests and responses could be validated to conform to the protocol. REST was much less strict (and easier to use), but you couldn't make a universal REST client because there was no set protocol to validate against.
The whole appeal of REST is that it wasn't a protocol like SOAP. You didn't need to adopt most of the recommendations. IIS at the time couldn't respond to anything other than GET/POST, so Microsoft REST APIs didn't use the verbs. A bug in a version of Flash player meant that it would only handle 200 responses, so we stopped using error codes and instead encoded error responses as 200s (sigh, a mistake we are still paying for today.)
From the jump the abstraction of REST leaked terribly. If you do /[customer]/[orders] and /[products] how do you get all the orders for a particular product without duplicating orders under products (a REST no-no). So 100% of all "REST" services I've worked with have always had an adjunct RPC API to handle the leaks.
That leakage and need for reporting in a uniform protocol was what gave us GraphQL. And GraphQL is a protocol where requests and responses can be validated to the point where we can build clients that are guaranteed to work based on that protocol.
So no, REST is not a protocol, and that's by design. GraphQL, gRPC, HTTP, FTP, TCP/IP, those are well structured communications protocols.
I’m using server actions with tRPC
Recommending GraphQL is a big mistake, it causes so much overhead that even big teams chocke on the complexity it causes.
I think you were a bit unfair to Graphql. People hitting your API is not a concern, I'm not sure where you got that information. Queries and mutations should be at minimum 2 up arrows, maybe 3, because you can define exactly what you want, quite easily.
wundergraph.com/blog/graphql_is_not_meant_to_be_exposed_over_the_internet#do-you-fully-understand-the-risks "GraphQL on the other hand, a single Query might result in thousands of calls on the controllers (resolvers) of the API. There is no simple way to solve this problem."
We ran into the issue at a major eCommerce company where we deployed end-user facing GQL with open requests and the API got frequently attacked and it was impossible to tell valid requests from malicious requests at the edge becauase the query was in the payload. We ended up going to white-listed query which defeats the purpose of GQL in the first place.
The query complexity issue is the reason why B2B GQL APIs have per-query cost calculations.
server actions feel wrong
love tRPC so far but saying it would be "easy to setup", for me as a beginner at least, is a LIE. I actually watched your nextjs trpc tutorial and you didn‘t even cover everything. The tRPC docs are ok at explaining the concepts but it wasn't fully clear for me, others do a better job. Maybe more examples might help. Ofc using t3 helps but I wanted to integrate it into an existing project
edit: also you need to be familiar with tanstack query to really utilize tRPC
course ad
All i know that rest is the stander
Actually, REST is not a standard, it's an "architectural style", which is why you'll never see a one size fits all REST client that doesn't have a ton of configuration options.
@@jherrI think what they mean is "de-facto"
@@akrishnadevotee Yeah, ok, that's fair. I just find it frustrating when folks call it a standard because I've never worked with a pure "REST" interface that didn't leak. They always need a non-standard set of RPCs for reports, multi-table inserts, etc..
I'll stick with Trpc and calling Trpc procedures from server actions
🫡