t3-oss / create-t3-app

The best way to start a full-stack, typesafe Next.js app
https://create.t3.gg
MIT License
25.08k stars 1.15k forks source link

feat: replace tRPC with server actions from NextJS13 #1456

Closed Lucasvo1 closed 1 year ago

Lucasvo1 commented 1 year ago

Is your feature request related to a problem? Please describe.

With server actions there is a more lightweight, zero configuration and type-safe way to handle data fetching.

Describe the solution you'd like to see

Remove tRPC and put in some examples using server actions.

Describe alternate solutions

No alternative solutions.

Additional information

No response

c-ehrlich commented 1 year ago

see https://github.com/t3-oss/create-t3-app/issues/1364

sscotth commented 1 year ago

TBF, I don't think server actions are referenced in #1364 only appDir. Either way, server actions are in alpha, not even beta yet. So it will very likely have significant breaking changes, replaced with something else, or dropped altogether. See the bleed responsibly axiom until it becomes stable.

Lucasvo1 commented 1 year ago

TBF, I don't think server actions are referenced in #1364 only appDir. Either way, server actions are in alpha, not even beta yet. So it will very likely have significant breaking changes, replaced with something else, or dropped altogether. See the bleed responsibly axiom until it becomes stable.

Well, like you see with the appDir migration in T3 now, it's better to start working on it now so that it's ready once it hits stable.

anaibol commented 1 year ago

I think Trpc integration on Nextjs is not only about data fetching but also about data state management on the frontend, it's built on top of React Query.

Kamahl19 commented 10 months ago

@c-ehrlich Server actions are now stable, do you plan doing this?

c-ehrlich commented 10 months ago

@c-ehrlich Server actions are now stable, do you plan doing this?

No.

We do "support" server actions, in the sense that it's a Next.js app and you can use them. But we have no plans to get rid of tRPC.

The Next.js team recommends using a data access layer for anything but quick prototyping. tRPC is that data layer for us.

In fact I'd recommend it even for quick prototyping, because:

Kamahl19 commented 10 months ago

The recommendation you linked only talks about the separation of concerns and not mixing data access with UI components. It says nothing about bringing 3rd party tools such as tRPC or Query into the stack. Achieving the "Data Access Layer" is also possible using "native/idiomatic" techniques which Server Actions are now, in Nextjs v14. Doing more with less should always be a preferred way.

tomer-dev commented 8 months ago

Adding to what @Kamahl19 said, I understand the part in the article on "Data access layer" as a recommendation for new projects to move the data access part into a "single library" where you can check input and auth, and on top of all you use DTOs.

After watching the "React+Servers=Confusion" video, I wonder what's the role of tRPC if we have the DTOs defined and we import server actions. Especially when the server actions can be imported on the client side.

I really love the work you do. I allow myself to raise this Q again as we learn and adapt to these new changes.

tomer-dev commented 8 months ago

Reddit discussion on keeping tRPC despite server actions in

After some research, let me know if tRPC integration with React Query and Next.js may be a reason for keeping tRPC even though with server actions we can RPC. From tRPC docs:

Our Next.js integration is built on top of our React Query Integration with some Next.js-specific APIs, to handle both client and server-side rendering.

Currently, making that server action call from the client will trigger a fetch call, extended by Next.js. Perhaps the benefits from server actions are still not more compelling than those offered by tRPC?

e.g. relying on React Query rather than Next.js App Router when it comes to caching and revalidation

markomitranic commented 7 months ago

@tomer-dev It is perfectly normal to use both react query and server actions, I use that in my projects:

  const { error } = useQuery({
    queryKey: ["posts"],
    queryFn: () => myServerAction("post-id"),
  });

With that said, I'd like to re-ignite your question one again. I'd like to have a discussion around the actual value of still using trpc. Looking at what is stated in this thread, let's break it one by one:

☑️ You must have a Data Access Layer - yes, but you can have it with either trpc or server actions, it doesn't really change much. ☑️ trpc gives you better dx - Not significantly better. T3 folks did build in some very nice things, like formatting errors, but on the other hand, the procedure declaration is uglier and more confusing. You win some, lose some. ☑️ trpc gives you better type safety - I'm not entirely sure what that even means. Zod ensures type safety, and linter helps. Both of these work exactly the same with server components. ☑️ you get react query integration in client components - as shown above, works exactly the same with server components. ☑️ it's no extra work for you because Create T3 App takes care of all of the initial setup - sure, but the whole point of this PR is to resolve this point.

So, no real difference in any of those points. I do wonder how trpc vs server actions affect your vercel costs tho.

issamwahbi commented 4 months ago

Hey,

@markomitranic , you are using a server action to fetch data with react-query. Nextjs are not recommanding this in their officiel documentation even if it works. From what I test, it fetch data with a POST request ..weird from web standards point of view !! it seems the recommanded approach from NEXTJS to fetch data is to use a server component...but not sur if that can cover all the cases.

In addition, I don't think server actions can yet replace tRPC functionalities. Server actions from client are a kind of RPCs. So you need from a good design point of view to handle data validation, authentication, authorization, error management ... before executing the server action logic. The best way in my opinion to do that is using a kind of middleware pattern. Some libraries out their like next-safe-action are trying to solve it.

I will even argue that at the moment tRPC is a better design decision than server actions. it gives more flexibility. For exemple if you need to reuse your api routes in a react native application.

in my opinion what will be the "ideal" solution is to be able to create tRPC routes as we do today and have a way to generate dynamically a server actions from it. with type safety and dynamic piping of the route middleware...

tomer-dev commented 4 months ago

It feels like React Server Actions are stepping on Next's toes, and it is confusing.

It is ok to have different patterns, but they should be declared as such.

React would go out of its way so much to imitate "better" a feature done by Next? they work so closely.

On Wed, May 29, 2024, 01:51 issamwahbi @.***> wrote:

Hey,

@markomitranic https://github.com/markomitranic , you are using a server action to fetch data with react-query. Nextjs are not recommanding this in their officiel documentation even if it works. From what I test, it fetch data with a POST request ..weird from web standards point of view !! it seems the recommanded approach from NEXTJS to fetch data is to use a server component...but not sur if that can cover all the cases.

In addition, I don't think server actions can yet replace tRPC functionalities. Server actions from client are a kind of RPCs. So you need from a good design point of view to handle data validation, authentication, authorization, error management ... before executing the server action logic. The best way in my opinion to do that is using a kind of middleware pattern. Some libraries out their like next-safe-action are trying to solve it.

I will even argue that at the moment tRPC is a better design decision than server actions. it gives more flexibility. For exemple if you need to reuse your api routes in a react native application.

in my opinion what will be the "ideal" solution is to be able to create tRPC routes as we do today and have a way to generate dynamically a server actions from it. with type safety and dynamic piping of the route middleware...

— Reply to this email directly, view it on GitHub https://github.com/t3-oss/create-t3-app/issues/1456#issuecomment-2136279587, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIXBBZCIW2J62JRBN5NO5ELZEUJ6RAVCNFSM6AAAAAAYUFKT6CVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMZWGI3TSNJYG4 . You are receiving this because you were mentioned.Message ID: @.***>

markomitranic commented 4 months ago

@issamwahbi I understand what you are saying. I just want to clarify 2 things.

Try to differentiate between the domain logic we have to write (which is literally the same for any transport method) and the transport method itself. Be it HTTP, trpc, ws, server actions, or even server components - you still have to do auth, sanitization and validation and api minimization. Yes the shape of doing it may vary but you still have to do it every single time.

Now, focusing on the differences between transport methods - it is perfectly fine to use POST, a good example of that is graphql. The main reason not to use POST is the (im)possibility of CDN level caching, which has plagued graphql for the past decade. And, it is literally the same for both trpc and actions, both are uncacheable in a similar way. That is the real reason why HTTP+GET is being always recommended - it thrives on caching. With that said, it is clear that this doesn't really make any difference between trpc and actions.

As for tanstack-query, that is a misconception - you can in fact use it with literally anything. You can use it with local async functions as well, for example. T3 Trpc uses it as well. So saying that they can't or shouldn't be used with server actions is kinda silly. But not so silly if you think about it - a large majority of the user base of NextJS is new to the basic backend concepts, and expect the NextJS team to set boundaries and best practices, which is percicely why they chose to say bad idea for fetching by server actions, instead of going into long winded explanations and endless github tickets, explaining "why your stuff is not being cached".

P.S. Kinda reminds me of why merge was decided to be the default git strategy over --rebase. Rebase is better on multiple fronts, including the conflict resolution, but merge is entirely idiot proof and that is what makes it a great sane default for everyone. :D

@tomer-dev oh wow not sure what you mean by that, has anything new happened?

markomitranic commented 4 months ago

The Next.js team recommends using a data access layer for anything but quick prototyping. tRPC is that data layer for us.

@c-ehrlich can you please expand on this, I'd love to learn more. I don't see how TRPC is "a data layer for us". The main thing that a data layer does is API minimization, which trpc has nothing to do with - we have to write our own DTOs before shipping data to the client.

Some other activities associated with having a data layer:

And none of these really have anything to do with our implementation of TRPC - the user has to write them themselves (yes, including input validation, which we use zod for).

Actually the only one out of all the data layer components, that we even remotely touch is that we require a zod definition as an input transformer, which again, nothing to do with trpc as a protocol, could be done with actions as well. So, our T3 trpc implementation basically just sets some general directions in terms of organizing our code elegantly, it does absolutely nothing to actually act as a data access layer.

So... what am I missing? Is there more functionality to our trpc implementation, that I don't know about yet :o

tomer-dev commented 4 months ago

Here's a trial to organize some thoughts:

In a video about server actions, Teo covered at least 4 different ways of dealing with the fetch call (Client/server component/function in a data layer/Form) Then, tRPC is put in doubt - as discussed above. Nevertheless, not all above methods infer a type.

As for Next, they costumized the fetch call. We love React Query though, and we'll probably continue to use it with Server actions.

Now Server components come in React 19.

What will you use?

Will you utilize: Next SC and tRPC, leaving SA for now? Next SC, tRPC and one/more of the server actions methods bove? Next SC, no tRPC because Server actions can generally cover the type inference, and no RSC because we have everything in Next?

Next but gradually move to RSC? Ane no tRPC because Server actions?

What's Next, just React?

On Wed, May 29, 2024, 10:22 Marko Mitranic @.***> wrote:

@issamwahbi https://github.com/issamwahbi I understand what you are saying. I just want to clarify 2 things.

Try to differentiate between the domain logic we have to write (which is literally the same for any transport method) and the transport method itself. Be it HTTP, trpc, ws, server actions, or even server components - you still have to do auth, sanitization and validation and api minimization. Yes the shape of doing it may vary but you still have to do it every single time.

Now, focusing on the differences between transport methods - it is perfectly fine to use POST, a good example of that is graphql. The main reason not to use POST is the (im)possibility of CDN level caching, which has plagued graphql for the past decade. And, it is literally the same for both trpc and actions, both are uncacheable in a similar way. That is the real reason why HTTP+GET is being always recommended - it thrives on caching. With that said, it is clear that this doesn't really make any difference between trpc and actions.

As for tanstack-query, that is a misconception - you can in fact use it with literally anything. You can use it with local async functions as well, for example. T3 Trpc uses it as well. So saying that they can't or shouldn't be used with server actions is kinda silly. But not so silly if you think about it - a large majority of the user base of NextJS is new to the basic backend concepts, and expect the NextJS team to set boundaries and best practices, which is percicely why they chose to say bad idea for fetching by server actions, instead of going into long winded explanations and endless github tickets, explaining "why your stuff is not being cached".

@tomer-dev https://github.com/tomer-dev oh wow not sure what you mean by that, has anything new happened?

— Reply to this email directly, view it on GitHub https://github.com/t3-oss/create-t3-app/issues/1456#issuecomment-2136827559, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIXBBZEMYROYBQPXY6QJAETZEWF3HAVCNFSM6AAAAAAYUFKT6CVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMZWHAZDONJVHE . You are receiving this because you were mentioned.Message ID: @.***>

tomer-dev commented 4 months ago

Another confusion is performing an RPC in the same file with the client logic.

React has made it so easy to make an RPC - It is easier than ever before to skip the security aspect (sanitation, API min, etc..), unintentionally over-sending information, or simply making an RPC in an unexpected manner, in unexpected places.. raising the question of conciseness.

Enough to look at the controversy around styled components, which struggled to find the balance between ease of use and the desire of fully encapsulating a component in a single file. (Never seen a pure Styled Component project, CSS is always very present)

Returning to SA, I like the good old Data Access layer approach. I wonder what is the benefit of having RPC logic in the same file with client code, seems like the server-client code is mixed enough at that point.

On Wed, May 29, 2024, 10:44 Tomer @.***> wrote:

Here's a trial to organize some thoughts:

In a video about server actions, Teo covered at least 4 different ways of dealing with the fetch call (Client/server component/function in a data layer/Form) Then, tRPC is put in doubt - as discussed above. Nevertheless, not all above methods infer a type.

As for Next, they costumized the fetch call. We love React Query though, and we'll probably continue to use it with Server actions.

Now Server components come in React 19.

What will you use?

Will you utilize: Next SC and tRPC, leaving SA for now? Next SC, tRPC and one/more of the server actions methods bove? Next SC, no tRPC because Server actions can generally cover the type inference, and no RSC because we have everything in Next?

Next but gradually move to RSC? Ane no tRPC because Server actions?

What's Next, just React?

On Wed, May 29, 2024, 10:22 Marko Mitranic @.***> wrote:

@issamwahbi https://github.com/issamwahbi I understand what you are saying. I just want to clarify 2 things.

Try to differentiate between the domain logic we have to write (which is literally the same for any transport method) and the transport method itself. Be it HTTP, trpc, ws, server actions, or even server components - you still have to do auth, sanitization and validation and api minimization. Yes the shape of doing it may vary but you still have to do it every single time.

Now, focusing on the differences between transport methods - it is perfectly fine to use POST, a good example of that is graphql. The main reason not to use POST is the (im)possibility of CDN level caching, which has plagued graphql for the past decade. And, it is literally the same for both trpc and actions, both are uncacheable in a similar way. That is the real reason why HTTP+GET is being always recommended - it thrives on caching. With that said, it is clear that this doesn't really make any difference between trpc and actions.

As for tanstack-query, that is a misconception - you can in fact use it with literally anything. You can use it with local async functions as well, for example. T3 Trpc uses it as well. So saying that they can't or shouldn't be used with server actions is kinda silly. But not so silly if you think about it - a large majority of the user base of NextJS is new to the basic backend concepts, and expect the NextJS team to set boundaries and best practices, which is percicely why they chose to say bad idea for fetching by server actions, instead of going into long winded explanations and endless github tickets, explaining "why your stuff is not being cached".

@tomer-dev https://github.com/tomer-dev oh wow not sure what you mean by that, has anything new happened?

— Reply to this email directly, view it on GitHub https://github.com/t3-oss/create-t3-app/issues/1456#issuecomment-2136827559, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIXBBZEMYROYBQPXY6QJAETZEWF3HAVCNFSM6AAAAAAYUFKT6CVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMZWHAZDONJVHE . You are receiving this because you were mentioned.Message ID: @.***>