server actions make progressively enhanced forms in react manageable. we had been reinventing forms on the front-end before since there was a pretty strong and often awkward boundary that was hard to send form requests over. this is why I appreciate the feature
I lean towards the seperate API for a few reasons: 1. Most of the databases I have to interact with have IP whitelists on them. Its possible get a fixed IP on Vercel but only on their super expensive enterprise plans 2. Puttkng the API layer closer to my database is better for performance on heavy CRUD usage 3. If you have long running server side tasks then you can fall foul of the serverless time limit on Vercel 4. I use a monorepo and tRPC to make it feel like it is still one application and to retain end to end type safety 5. The API is reusable if we want to have extra applications, such as a mobile app The cons of this approach are as you say, the extra headache of maintenance and CI/CD. Im considering trying SST to deploy Next.js in our AWS environment to get around some of the security issues though.
Surprisingly well made and comprehensive video. You knocked it out of the park with the analysis and the showcase of how this can be orchestrated, as well as what server actions actually mean. One thing I think you could have touched upon more, and a thing that I see lots of people missing, is that server actions - while creating the endpoints and doing the calls for you automatically - expose your server functions as route handlers to the public. This might not be obvious and I foresee a lot of issues because people will not sanitize the function params because they will miss the fact that it's a public request input.
Totally agree. Though I thought by going over the fact that an SA is an API, just not an API that is generated for you and not one that you control, that I covered that. But I appreciate the feedback.
Great content! Thanks for putting this together. In these times of constantly evolving full-stack frameworks, it’s helpful to see the different possibilities laid out with their pros and cons. As you mentioned, I believe a combination of these patterns is often the best approach, depending on the specific requirements. 🙏🚀
I really agree with you there's no winner here, it all depends on some factors like type of app, size of team, whether there's gonna be a mobile app or not etc
It’s the classic case where “separation of concerns” is great general advice, but we can’t really agree on what’s an individual concern 😂 The component-based approach that React popularised redefined whether a single component should be “concerned” about the html semantics, “looks” via styling / css, and interactivity via JS. I’d say most agree now that it’s fine for all that to count as a single concern, and often even keep all the related code in the one file (the component itself). Maybe we’ll see server actions like that in 5 years, with hindsight. I like the idea of the component, where its “one concern” is getting you through… Stripe checkout! Great video overall! I like the server actions with extracted “api modules” the most, the second example!.. unless you do indeed have to maintain a dedicated API for a mobile app etc. If that’s a concern, then it redefines what I consider an appropriate concern for a component 😄
Most in the react world might see component coupling as 'fine', but i promise you other tech stacks do NOT see it that way. Of course RSC to that crowd is just taking a bad idea to the PHP2k extreme.
Great video! Just to clarify, in the client-to-msvc-proxy example, why are the cons of the client-to-mscv no longer relevant? I.e. - Multiple servers to maintain - Larger security surface area If you proxy the request using a local Next server to the microservice, do the above points not still hold?
after seeing only 2 of your videos around new nextjs zustand and one more around client vs server with approuter method instead of pages. I somehow believe you are quite credible, knowing your stuff. Thanks! I hope someday when these skills i start earning from, i can thank you with a dinner or something someday. Thanks Jack. :D
I would use the more simple to maintain, adding too much of extra layers, and abstractions, just make the application very hard to maintain and understand in the long run
For posterity and from the viewpoint of learners: I think it's unfortunate to use slugs in the example, because of the functional use of the word too. It adds an extra layer of complexity imo
Maybe I'm hung up on details, but it bothers me a bit that the examples out there use the formAction of a button. To me it implies the action would work without a form, but that is ofc not the case. But I guess with a form element the examples would look less cool. I wonder if we'll end up wrapping React components in arbitrary forms, just to have independent buttons replace their actions. And then there's startTransition for calling Server Actions outside forms, but without progressive enhancement. Which and when should we use each is a bit muddy.
Shouldn't one use parameterized query and ? instead of ${} (interpolation), if one wanted to stay on the safe side? Edit: Figured it out. The framework does make parameterized query out of (sql) tagged template literals.
You missed one pattern at the very end. Remove the Next.JS API layer and just use server action for form submissions that directly call the microservice. That way, you can still do one of the features provided by server actions, i.e. no client-side-javascript.
I missed a bunch of combinations actually. That's why I mentioned at the end that these are patterns that you can use in combinations. But, yeah, the combinatorics were higher than what I could fit into 15-20 minutes. 😂
I still think Server Actions should be considered "server transformations". It can be useful for returning back data to the client from an action but it shouldn't have any kind of elevated permissions. Options 1 doesn't automatically give extra permissions but if another dev decides to change that inline function, it could easily give additional access and that change could be overlooked during review. Same problem with option 2 but at least server actions could be grouped together and are easier to find during review. The downside to both is the "implicit API" being created during compile. Vercel offers version skew protection that can help here, tying actions back to individual deployments, but that may not be helpful if self-hosting (I'm not sure if feature is only specific to Vercel?). But it could still be problematic if you're going with option 1 (what if the database has been migrated, for example?). Option 3 feels the most clear without introducing headaches of managing an additional microservice. With a solution like tRPC or Prim+RPC (my own RPC library, more transparent like server actions) you get the benefits of server actions without a required compile step. You also can protect against version skew yourself, without managing an additional server. They're like more predictable server actions which is kind of the best of both worlds. But Option 3 is most powerful combined with option 1: you can write a full API (without concern for UI component needs) but then access and transform that data in a Server Action, specific to what the UI components need. That "server transformation" option is how I plan to use Server Actions.
Approaches 1-4 are great for fullstack, approach 6 is default way for frontend app. But approach 5 looks overly engineered and under performing solution. Why and where would it be better than approach 6?
You can create an API when you need it. Having and maintaining API is a burden. And if you don't need it now, don't create it. I realized it when I wrote my first app using Meteor. The absence of an API helps you to move forward up to 10 times faster.
Great video What is the problem if the Next app speaks directly to the database instead of through microservice? I guess that you would prefer a microservice if you have two different Next apps interacting with the same API?
I personally don't have a problem with it, unless, as you say, you have to apps altering the same DB. They would have to align on the schema and all that, so the DB should probably be behind a microservice or at least access to the DB abstracted into a shared library.
They're just trying to help with the BFF. Some (many?) backends are just passing data between the browser and the db, and they only need a BFF. If you need to independently scale and/or deploy multiple services that are consumed by multiple clients, eg mobile, desktop, paid api usage, then these new features aren't really for you. I'm not too interested in progressive enhancement, but I am interested in iteration velocity. @jack, which architecture was the fastest to code up? I'd really like to see some analysis on how much faster we can ship features with these new tools (when used in the right context).
Wouldn't the majority of realistic cases fall into Microservices (or just plain services) proxy without using Clerk (why is it considered a standard case anyway?) though? I mean most would be that we already have API(s), most of the times with their auth service, being consumed by web , mobile etc. It seems like these fit into kind of niche scenarios or new projects where you go "full monolith" next. It would be nice to see solutions like Laravel/Inertia.
Adding Clerk at both layers means that each layer is independently secured. Folks often use something like Amazon's API Gateway for this. If the API doesn't get the user ID from the bearer token or cookie JWT then it would get it as a parameters. Which would mean that any intruder that was able to penetrate the web server layer would have access to all user data since they could send requests as anyone. In addition bugs in the UI layer's handling of auth could also result in data leaks.
@@jherr I can't really imagine anyone getting auth user id through params. But really my question was why are we tightly coupling Clerk dependency ? If we think about apps want to migrate to nextjs (or react but since nextjs is promoted and stated as THE way) this is kind of a no go. Why can't we have clear and production examples with an express/php/python auth server ? Why the 3rd party dep? I do understand the benefits of these 3rd party services but thats not the most widely used solutions and it seems to be quite a hurdle to implement any other solution.
@@skapator Literally it was just easier. Clerk just has a very easy DX. Feel free to PR the repo with another version with OSS auth and we can keep that in another branch for folks and document that.
@@jherr thats a pretty cool idea. I am not undermining Clerk or the video (actually the video was extremely enlightening), believe me I do understand the benefits and the DX for sure. But it is hard to sell on already established apps.Can't change stack or providers or add a 3rd party dep just because.
@@skapator Ok, cool. This is more of a "patterns" video that shows several different ways of either using server actions or an API where that API is either proxied or direct. And it shows how to do that in an authenticated way, which is something that was not shown in the original presentation but which is critical in any real world scenario. I will say that nothing here is unique to Clerk. All of these OAuth vendors work pretty much the same way. I've used nextauth, auth/core, auth0, they all have the same basic pieces: some components to handle login/logout, a way to get the active user from either the session cookie or the bearer token on the server, and a hook to get the user information on the client. The only differences are in the library names, the cookie names, and that kind of stuff.
I see no harm in having DB requests in the client code. So long as the server handler is sanitizing the data coming at it from those requests. It's not really any different than passing a request via axios/graphql etc. However, meshing together html AND a request like that is stupid. There should be a separation of the data and the component, otherwise it has no re-usability. Both those opening examples were terrible.
Let me tell you one very good usecase with server action that i found, I was working with solana anchor project where i had to load IDL (huge json file to serialize and desterilize raw binary ) in front-end , and its just not json also the library to generate the transactions . And this was making page size huge more than mb. So with server actions i am able to generate the transactions in server and pass it to client and pages are now around 200kb, yes its definitely possible in other way but actions makes the flow really simple, i can't imagine going 6 layers of graphql for this kind of things.
My main issue with the server actions is the complete lack of validation in almost any example. Sql injection is the least of your problems if you dont validate any input.
Vercel probably expect most developers to use zod or similar to validate input. Next doesn't try to provide this natively and it isn't part of the server actions update, so they don't necessarily need to show it in their example.
@@oliversaxon8656 that's a bit weird because server actions without user input validation are basically a security risk. It's really weird they didn't bundle zod or some other similar library.
Because those things are implementation details. Validation can be done in many different ways at different levels. Next.js docs doesn't explain how to architect your app for every feature, because there's multiple ways to go around it depending on your requirements and needs and it's just noise. If you're delivering _anything_ to production environment, you should always think about these implications. In fact the Next.js docs _does_ have _recommendations_ for doing validation. A simple search will get you the information you seek.
This is usually a sign of including env variables in client-side closures. Do you have all your server actions in a completely separate file marked with "use server"?
@@zombiefacesupreme I’ve just tried the simplest of integration: .env: “NEXT_RESEND_API_KEY=******** (no quotes)” app/(pages)/about/page.tsx: “”use client” const apiKey = process.env.NEXT_RESEND_API_KEY.” It won’t retrieve it with or without the “use client” it equals undefined. I can’t make it public… so I guess the best thing to do is make an api call to retrieve it?
Yeah, for the stuff you need up on the client you have to prefix the env variable with NEXT_PUBLIC_. And there is a big gotcha here. That env variable is frozen at BUILD time.
Thank you fot this video, now I see that mix server and client is bad idea. I have suggestion for your next video, turborepo, docker, express, prisma, nextjs. There is docker examples on their website. Main idea is that it should start in one command. I need this project as part of my portfolio, and it's important to make it easier to start for recruiters
I struggle to understand the benefits of the new nextjs app folder approach. I am not migrating any project to it for sure. Might as well migrate to a totally different framework at this point.
I still have yet to use a single server action. I don’t really see the use case for it. So far pushing the client side stuff superrrrr far to the edges and just handling any server stuff with trpc or the odd axios function in those components handles everything I can imagine.
Great rundown of pros and cons. As a C#/.NET developer, it still feels "wrong" to have a mostly-frontend framework like NextJS responsible for so much backend code. But also, I see this is the way of NextJS 14 - it's becoming more fullstack than ever before. However, the last couple of examples you put out in this video confirms me in believing it can be done more or less properly. However, I would still like to see more type safety on the SQL calls, other than raw SQL queries. In C# we have ORMs like Dapper that can help us increase the safety of our calls to the SQL server. Is there a proper SQL-ORM for NextJS?
Prisma and drizzle are the most popular ORMs for nextjs/typescript. I feel that ORMs have given us too much reliance on them though, it's always a good idea for validation to occur before ever touching a database with Zod being the most commonly used. You can have it client-side for form helpers as well as server side for sanitizing post data (never trust client input).
The problem with the sql tag template call is it it unnecessarily complicated and raises questions. Function arguments are parsed from the string, ok where are they defined? How is the scoping? Totally unnecessary when you could just use a function with usual query placeholder syntax and parameters.
I still don't understand the uproar. It was just an example showing server actions, they are not going to build a backend and show every controller, that wasn't the scope of the presentation. Doesn't mean you should do what was on the screen with your applications. I've also seen multiple complains showing lack of knowledge, like claims of SQL injection or that you "should not include SQL in the front end" when clearly that function doesn't run on the front end.
I don't understand why you can't use server actions for all the scenarios. Why do you have to move to client components just because your using an API?
I think much of the uproar could have been avoided if they named their db function "sanitizeSQLQuery`SELECT * FROM TABLE`" instead of "sql`SELECT * FROM TABLE`". It's like wearing a cloth mask and Coronavirus: A "string on your finger" mental reminder moreso than a bulletproof physical barrier.
@@jherr I am agreeing with you -- That was my point. People don't realize the inputs are being sanitized because it is not implied by the name. They could rename that exact same "sql``" call as "safeSql``" or "sanitizedSql``" to remove any possible confusion.
My problem with the example they made, is that generally components should try not to mix front- and backend code. I would especially not like to see SQL/ORM instructions in a client component, even if it only runs on the server. So with that said, imo server actions shouldn't touch any database API directly. Server actions send a request, and that endpoint handles the database actions.
Wait, what the hell is a "client component that only runs on the server"? My understanding was that "client" components run first on the server and then on the client, while server components run exclusively on the server.
You cannot have server actions on client components. Client components are rendered both on the server and client, whereas server components are execlusively run on the server, as @rod6722 correctly mentions. Separation of concerns is a subjective matter, and you can do whatever you want. Move things where you want them. But premature abstraction has almost always resulted in poor architectural decisions due to lack of context and presumptions. Write the thing you need first, refactor later as you go.
The biggest problem of next 14 is not server actions, but a terrible runtime performance degradation even compared to nextjs pages router, and if compared to sveltekit or astro 10x time less capable to serve SSR requests per second. Nobody cares about this, but it’s really maters, and no, vercel cloud with scaling by cloud function is not a solution to this
You're talking about Next.js 14 degradation, or App Router degradation, compared to Pages Router? If the former, what specific new faeture of Next.js 14, of which there aren't many, would be the cause?
I found this next.js latest version so annoying. I can't even use some pre built libraries like calendar, schedulers, Charts etc just cos some of their actions don't work on SSR 🤦♂️🤦♂️
@@jherr I dug my ass trying to find out why REACT BIG CALENDAR was not working properly. Came to know this doesn't work with SSR. had to switch to REACT.JS 😑😑
server actions make progressively enhanced forms in react manageable.
we had been reinventing forms on the front-end before since there was a pretty strong and often awkward boundary that was hard to send form requests over. this is why I appreciate the feature
Server actions + 1 abstraction layer is the best imo.
You could still use the abstraction layer for some API route if really needed.
Cool I don't care.
@@TheAliAhadIf you are going to discredit someone you better provide some solid arguments, else you’re just discrediting yourself.
@@TheAliAhad master of clean architecture, show us the correct way
I lean towards the seperate API for a few reasons:
1. Most of the databases I have to interact with have IP whitelists on them. Its possible get a fixed IP on Vercel but only on their super expensive enterprise plans
2. Puttkng the API layer closer to my database is better for performance on heavy CRUD usage
3. If you have long running server side tasks then you can fall foul of the serverless time limit on Vercel
4. I use a monorepo and tRPC to make it feel like it is still one application and to retain end to end type safety
5. The API is reusable if we want to have extra applications, such as a mobile app
The cons of this approach are as you say, the extra headache of maintenance and CI/CD. Im considering trying SST to deploy Next.js in our AWS environment to get around some of the security issues though.
Absolutely right
Surprisingly well made and comprehensive video. You knocked it out of the park with the analysis and the showcase of how this can be orchestrated, as well as what server actions actually mean.
One thing I think you could have touched upon more, and a thing that I see lots of people missing, is that server actions - while creating the endpoints and doing the calls for you automatically - expose your server functions as route handlers to the public. This might not be obvious and I foresee a lot of issues because people will not sanitize the function params because they will miss the fact that it's a public request input.
Totally agree. Though I thought by going over the fact that an SA is an API, just not an API that is generated for you and not one that you control, that I covered that. But I appreciate the feedback.
I just found out your channel yesterday and the way you teach is fascinating sir, eagerly waiting for your complete Nextjs course!
Great content! Thanks for putting this together. In these times of constantly evolving full-stack frameworks, it’s helpful to see the different possibilities laid out with their pros and cons. As you mentioned, I believe a combination of these patterns is often the best approach, depending on the specific requirements. 🙏🚀
Marvelous, in the midst of a project and this fills in many gaps. Always thankful.
Really simple and straight forwards; I love it.
I really agree with you there's no winner here, it all depends on some factors like type of app, size of team, whether there's gonna be a mobile app or not etc
It’s the classic case where “separation of concerns” is great general advice, but we can’t really agree on what’s an individual concern 😂
The component-based approach that React popularised redefined whether a single component should be “concerned” about the html semantics, “looks” via styling / css, and interactivity via JS. I’d say most agree now that it’s fine for all that to count as a single concern, and often even keep all the related code in the one file (the component itself).
Maybe we’ll see server actions like that in 5 years, with hindsight. I like the idea of the component, where its “one concern” is getting you through… Stripe checkout!
Great video overall! I like the server actions with extracted “api modules” the most, the second example!.. unless you do indeed have to maintain a dedicated API for a mobile app etc.
If that’s a concern, then it redefines what I consider an appropriate concern for a component 😄
Most in the react world might see component coupling as 'fine', but i promise you other tech stacks do NOT see it that way. Of course RSC to that crowd is just taking a bad idea to the PHP2k extreme.
Great video! Just to clarify, in the client-to-msvc-proxy example, why are the cons of the client-to-mscv no longer relevant? I.e.
- Multiple servers to maintain
- Larger security surface area
If you proxy the request using a local Next server to the microservice, do the above points not still hold?
Yeah, it's additive, you are right.
after seeing only 2 of your videos around new nextjs zustand and one more around client vs server with approuter method instead of pages. I somehow believe you are quite credible, knowing your stuff. Thanks! I hope someday when these skills i start earning from, i can thank you with a dinner or something someday. Thanks Jack. :D
Thank you!
I would use the more simple to maintain, adding too much of extra layers, and abstractions, just make the application very hard to maintain and understand in the long run
Superb video jack!!
For posterity and from the viewpoint of learners: I think it's unfortunate to use slugs in the example, because of the functional use of the word too. It adds an extra layer of complexity imo
Maybe I'm hung up on details, but it bothers me a bit that the examples out there use the formAction of a button. To me it implies the action would work without a form, but that is ofc not the case. But I guess with a form element the examples would look less cool. I wonder if we'll end up wrapping React components in arbitrary forms, just to have independent buttons replace their actions. And then there's startTransition for calling Server Actions outside forms, but without progressive enhancement. Which and when should we use each is a bit muddy.
There's a form element that wraps all the buttons.
Shouldn't one use parameterized query and ? instead of ${} (interpolation), if one wanted to stay on the safe side? Edit: Figured it out. The framework does make parameterized query out of (sql) tagged template literals.
You missed one pattern at the very end. Remove the Next.JS API layer and just use server action for form submissions that directly call the microservice. That way, you can still do one of the features provided by server actions, i.e. no client-side-javascript.
I missed a bunch of combinations actually. That's why I mentioned at the end that these are patterns that you can use in combinations. But, yeah, the combinatorics were higher than what I could fit into 15-20 minutes. 😂
I still think Server Actions should be considered "server transformations". It can be useful for returning back data to the client from an action but it shouldn't have any kind of elevated permissions.
Options 1 doesn't automatically give extra permissions but if another dev decides to change that inline function, it could easily give additional access and that change could be overlooked during review. Same problem with option 2 but at least server actions could be grouped together and are easier to find during review.
The downside to both is the "implicit API" being created during compile. Vercel offers version skew protection that can help here, tying actions back to individual deployments, but that may not be helpful if self-hosting (I'm not sure if feature is only specific to Vercel?). But it could still be problematic if you're going with option 1 (what if the database has been migrated, for example?).
Option 3 feels the most clear without introducing headaches of managing an additional microservice. With a solution like tRPC or Prim+RPC (my own RPC library, more transparent like server actions) you get the benefits of server actions without a required compile step. You also can protect against version skew yourself, without managing an additional server. They're like more predictable server actions which is kind of the best of both worlds.
But Option 3 is most powerful combined with option 1: you can write a full API (without concern for UI component needs) but then access and transform that data in a Server Action, specific to what the UI components need. That "server transformation" option is how I plan to use Server Actions.
Maan, dude bro thanks
Approaches 1-4 are great for fullstack, approach 6 is default way for frontend app. But approach 5 looks overly engineered and under performing solution. Why and where would it be better than approach 6?
You can create an API when you need it. Having and maintaining API is a burden. And if you don't need it now, don't create it. I realized it when I wrote my first app using Meteor. The absence of an API helps you to move forward up to 10 times faster.
Agreed
Great video What is the problem if the Next app speaks directly to the database instead of through microservice? I guess that you would prefer a microservice if you have two different Next apps interacting with the same API?
I personally don't have a problem with it, unless, as you say, you have to apps altering the same DB. They would have to align on the schema and all that, so the DB should probably be behind a microservice or at least access to the DB abstracted into a shared library.
5:06 What plugin should I use to highlight my code?
I don't use a plugin. I use screenFlow to do the highlighting.
They're just trying to help with the BFF. Some (many?) backends are just passing data between the browser and the db, and they only need a BFF. If you need to independently scale and/or deploy multiple services that are consumed by multiple clients, eg mobile, desktop, paid api usage, then these new features aren't really for you.
I'm not too interested in progressive enhancement, but I am interested in iteration velocity. @jack, which architecture was the fastest to code up? I'd really like to see some analysis on how much faster we can ship features with these new tools (when used in the right context).
Wouldn't the majority of realistic cases fall into Microservices (or just plain services) proxy without using Clerk (why is it considered a standard case anyway?) though? I mean most would be that we already have API(s), most of the times with their auth service, being consumed by web , mobile etc.
It seems like these fit into kind of niche scenarios or new projects where you go "full monolith" next.
It would be nice to see solutions like Laravel/Inertia.
Adding Clerk at both layers means that each layer is independently secured. Folks often use something like Amazon's API Gateway for this. If the API doesn't get the user ID from the bearer token or cookie JWT then it would get it as a parameters. Which would mean that any intruder that was able to penetrate the web server layer would have access to all user data since they could send requests as anyone. In addition bugs in the UI layer's handling of auth could also result in data leaks.
@@jherr I can't really imagine anyone getting auth user id through params. But really my question was why are we tightly coupling Clerk dependency ? If we think about apps want to migrate to nextjs (or react but since nextjs is promoted and stated as THE way) this is kind of a no go. Why can't we have clear and production examples with an express/php/python auth server ? Why the 3rd party dep? I do understand the benefits of these 3rd party services but thats not the most widely used solutions and it seems to be quite a hurdle to implement any other solution.
@@skapator Literally it was just easier. Clerk just has a very easy DX. Feel free to PR the repo with another version with OSS auth and we can keep that in another branch for folks and document that.
@@jherr thats a pretty cool idea. I am not undermining Clerk or the video (actually the video was extremely enlightening), believe me I do understand the benefits and the DX for sure. But it is hard to sell on already established apps.Can't change stack or providers or add a 3rd party dep just because.
@@skapator Ok, cool. This is more of a "patterns" video that shows several different ways of either using server actions or an API where that API is either proxied or direct. And it shows how to do that in an authenticated way, which is something that was not shown in the original presentation but which is critical in any real world scenario.
I will say that nothing here is unique to Clerk. All of these OAuth vendors work pretty much the same way. I've used nextauth, auth/core, auth0, they all have the same basic pieces: some components to handle login/logout, a way to get the active user from either the session cookie or the bearer token on the server, and a hook to get the user information on the client. The only differences are in the library names, the cookie names, and that kind of stuff.
I see no harm in having DB requests in the client code. So long as the server handler is sanitizing the data coming at it from those requests. It's not really any different than passing a request via axios/graphql etc.
However, meshing together html AND a request like that is stupid. There should be a separation of the data and the component, otherwise it has no re-usability. Both those opening examples were terrible.
Let me tell you one very good usecase with server action that i found, I was working with solana anchor project where i had to load IDL (huge json file to serialize and desterilize raw binary ) in front-end , and its just not json also the library to generate the transactions . And this was making page size huge more than mb. So with server actions i am able to generate the transactions in server and pass it to client and pages are now around 200kb, yes its definitely possible in other way but actions makes the flow really simple, i can't imagine going 6 layers of graphql for this kind of things.
You don't need server-actions for this, you can do it with basic api-route. But I quess api-route is server-action (with some tweeks to path)
My main issue with the server actions is the complete lack of validation in almost any example. Sql injection is the least of your problems if you dont validate any input.
or error handling...
Vercel probably expect most developers to use zod or similar to validate input. Next doesn't try to provide this natively and it isn't part of the server actions update, so they don't necessarily need to show it in their example.
@@oliversaxon8656 that's a bit weird because server actions without user input validation are basically a security risk. It's really weird they didn't bundle zod or some other similar library.
Because those things are implementation details. Validation can be done in many different ways at different levels. Next.js docs doesn't explain how to architect your app for every feature, because there's multiple ways to go around it depending on your requirements and needs and it's just noise.
If you're delivering _anything_ to production environment, you should always think about these implications. In fact the Next.js docs _does_ have _recommendations_ for doing validation. A simple search will get you the information you seek.
How is that React's problem? Isn't that an issue in the backend as well if you don't validate and sanitize input?
Cool, thanks a lot!
I’m struggling with env variables. With the split in Serverside / client side, it doesn’t seem to want to pull the env variable.
This is usually a sign of including env variables in client-side closures. Do you have all your server actions in a completely separate file marked with "use server"?
@@zombiefacesupreme I’ve just tried the simplest of integration: .env: “NEXT_RESEND_API_KEY=******** (no quotes)” app/(pages)/about/page.tsx: “”use client” const apiKey = process.env.NEXT_RESEND_API_KEY.” It won’t retrieve it with or without the “use client” it equals undefined. I can’t make it public… so I guess the best thing to do is make an api call to retrieve it?
@@zombiefacesupreme 16:03 this seems like what I’ll need to implement to get it to read the env variable I think?
Yeah, for the stuff you need up on the client you have to prefix the env variable with NEXT_PUBLIC_. And there is a big gotcha here. That env variable is frozen at BUILD time.
@@jherr that exposes the api key to the browser allowing malicious users to take the key and use it for their own right?
Thank you fot this video, now I see that mix server and client is bad idea. I have suggestion for your next video, turborepo, docker, express, prisma, nextjs. There is docker examples on their website. Main idea is that it should start in one command. I need this project as part of my portfolio, and it's important to make it easier to start for recruiters
I struggle to understand the benefits of the new nextjs app folder approach. I am not migrating any project to it for sure. Might as well migrate to a totally different framework at this point.
Only real usefull thing they did is nested router. Rest of features (caching, server-actions, RSC) is real barrier for migration to new router
I still have yet to use a single server action. I don’t really see the use case for it. So far pushing the client side stuff superrrrr far to the edges and just handling any server stuff with trpc or the odd axios function in those components handles everything I can imagine.
Great rundown of pros and cons. As a C#/.NET developer, it still feels "wrong" to have a mostly-frontend framework like NextJS responsible for so much backend code. But also, I see this is the way of NextJS 14 - it's becoming more fullstack than ever before. However, the last couple of examples you put out in this video confirms me in believing it can be done more or less properly. However, I would still like to see more type safety on the SQL calls, other than raw SQL queries. In C# we have ORMs like Dapper that can help us increase the safety of our calls to the SQL server. Is there a proper SQL-ORM for NextJS?
Prisma and drizzle are the most popular ORMs for nextjs/typescript. I feel that ORMs have given us too much reliance on them though, it's always a good idea for validation to occur before ever touching a database with Zod being the most commonly used. You can have it client-side for form helpers as well as server side for sanitizing post data (never trust client input).
@@NicolasSouthern Nice, Prisma + Zod sounds amazing.
@@schintusDon't get too excited, entity framework is miles ahead of these options.
@@alexbecar977IMHO Next/JS should never call a SQL server itself. It should call an external API (not NextJS APIs) to get its data 👌🏻
The problem with the sql tag template call is it it unnecessarily complicated and raises questions. Function arguments are parsed from the string, ok where are they defined? How is the scoping?
Totally unnecessary when you could just use a function with usual query placeholder syntax and parameters.
I still don't understand the uproar. It was just an example showing server actions, they are not going to build a backend and show every controller, that wasn't the scope of the presentation. Doesn't mean you should do what was on the screen with your applications.
I've also seen multiple complains showing lack of knowledge, like claims of SQL injection or that you "should not include SQL in the front end" when clearly that function doesn't run on the front end.
I don't understand why you can't use server actions for all the scenarios. Why do you have to move to client components just because your using an API?
You could use SAs for it all, but then you don't control the API so if there are other clients that's a problem.
@@jherr What do you mean by "you don't control the API"?
@@nyxandtyryou don’t control the name of the route, the parameters, what verb is used, or how the request is processed before it gets to you
Will you make Nextjs14series pls sir?
I think much of the uproar could have been avoided if they named their db function "sanitizeSQLQuery`SELECT * FROM TABLE`" instead of "sql`SELECT * FROM TABLE`".
It's like wearing a cloth mask and Coronavirus: A "string on your finger" mental reminder moreso than a bulletproof physical barrier.
Well, except that it is sanitized by @vercel/postgres.
@@jherr I am agreeing with you -- That was my point.
People don't realize the inputs are being sanitized because it is not implied by the name. They could rename that exact same "sql``" call as "safeSql``" or "sanitizedSql``" to remove any possible confusion.
@@jibreelkeddo7030 Ah, fair, agreed.
What browser are you using ?
Probably Arc.
My problem with the example they made, is that generally components should try not to mix front- and backend code. I would especially not like to see SQL/ORM instructions in a client component, even if it only runs on the server.
So with that said, imo server actions shouldn't touch any database API directly. Server actions send a request, and that endpoint handles the database actions.
Wait, what the hell is a "client component that only runs on the server"? My understanding was that "client" components run first on the server and then on the client, while server components run exclusively on the server.
You cannot have server actions on client components. Client components are rendered both on the server and client, whereas server components are execlusively run on the server, as @rod6722 correctly mentions.
Separation of concerns is a subjective matter, and you can do whatever you want. Move things where you want them. But premature abstraction has almost always resulted in poor architectural decisions due to lack of context and presumptions. Write the thing you need first, refactor later as you go.
oof. Clear as mud.
The biggest problem of next 14 is not server actions, but a terrible runtime performance degradation even compared to nextjs pages router, and if compared to sveltekit or astro 10x time less capable to serve SSR requests per second. Nobody cares about this, but it’s really maters, and no, vercel cloud with scaling by cloud function is not a solution to this
You're talking about Next.js 14 degradation, or App Router degradation, compared to Pages Router? If the former, what specific new faeture of Next.js 14, of which there aren't many, would be the cause?
I found this next.js latest version so annoying. I can't even use some pre built libraries like calendar, schedulers, Charts etc just cos some of their actions don't work on SSR 🤦♂️🤦♂️
Yeah, pages router was better for that, but even then some library components weren't SSR compatible either.
@@jherr I dug my ass trying to find out why REACT BIG CALENDAR was not working properly. Came to know this doesn't work with SSR. had to switch to REACT.JS 😑😑
So in conclusion the best practice is not to use it 😂
1st view