NextJS 14 Server Action Controversy!

Поділитися
Вставка
  • Опубліковано 8 чер 2024
  • Learn five system design patterns that you can use with various combinations of server actions, APIs and microservices.
    Code: github.com/jherr/server-actio...
    👉 Upcoming NextJS course: pronextjs.dev
    👉 Don't forget to subscribe to this channel for more updates: bit.ly/2E7drfJ
    👉 Discord server signup: / discord
    👉 VS Code theme and font? Night Wolf [black] and Operator Mono
    👉 Terminal Theme and font? oh-my-posh with powerlevel10k_rainbow and SpaceMono NF
    0:00 Introduction
    1:27 Short Postgres/ Clerk Setup
    4:10 Server Action Direct to DB
    7:24 Server Action To Local SQL Module
    10:10 API to Local SQL Module
    14:02 Application And Microservice
    17:38 Application to Microservice Proxied
    20:31 Outro
  • Наука та технологія

КОМЕНТАРІ • 102

  • @Dev-Siri
    @Dev-Siri 7 місяців тому +16

    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

  • @tom.watkins
    @tom.watkins 7 місяців тому +17

    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.

  • @jeromesnail
    @jeromesnail 7 місяців тому +22

    Server actions + 1 abstraction layer is the best imo.
    You could still use the abstraction layer for some API route if really needed.

    • @jeromesnail
      @jeromesnail 7 місяців тому +2

      Cool I don't care.

    • @dawid_dahl
      @dawid_dahl 6 місяців тому +2

      @@TheAliAhadIf you are going to discredit someone you better provide some solid arguments, else you’re just discrediting yourself.

    • @bastek338
      @bastek338 6 місяців тому

      @@TheAliAhad master of clean architecture, show us the correct way

  • @dwin9983
    @dwin9983 5 місяців тому +1

    I just found out your channel yesterday and the way you teach is fascinating sir, eagerly waiting for your complete Nextjs course!

  • @srymisclick
    @srymisclick 7 місяців тому +5

    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.

    • @jherr
      @jherr  7 місяців тому +1

      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.

  • @VincentFulco
    @VincentFulco 7 місяців тому +1

    Marvelous, in the midst of a project and this fills in many gaps. Always thankful.

  • @anasouardini
    @anasouardini 7 місяців тому +2

    Really simple and straight forwards; I love it.

  • @olyvar
    @olyvar 7 місяців тому +1

    Superb video jack!!

  • @umarmuhammadzakari4585
    @umarmuhammadzakari4585 7 місяців тому +2

    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

  • @appstuff6565
    @appstuff6565 7 місяців тому

    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

    • @jherr
      @jherr  7 місяців тому +1

      Thank you!

  • @rust2411
    @rust2411 7 місяців тому +1

    Maan, dude bro thanks

  • @BlueeyesChineseguy
    @BlueeyesChineseguy 7 місяців тому +3

    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?

    • @jherr
      @jherr  7 місяців тому +1

      Yeah, it's additive, you are right.

  • @alexandershemelin6605
    @alexandershemelin6605 7 місяців тому

    Cool, thanks a lot!

  • @jmagrippis
    @jmagrippis 7 місяців тому +3

    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 😄

    • @adambickford8720
      @adambickford8720 7 місяців тому +1

      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.

  • @user-ik7rp8qz5g
    @user-ik7rp8qz5g 7 місяців тому +3

    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?

  • @denissorn
    @denissorn 7 місяців тому +2

    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.

  • @gamerclips8895
    @gamerclips8895 7 місяців тому +16

    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

  • @eulersson
    @eulersson 3 місяці тому

    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?

    • @jherr
      @jherr  3 місяці тому

      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.

  • @ilkkaouto
    @ilkkaouto 7 місяців тому +2

    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.

    • @jeromesnail
      @jeromesnail 7 місяців тому +1

      There's a form element that wraps all the buttons.

  • @tonajki
    @tonajki 6 місяців тому +1

    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

  • @AndreyDyatlov
    @AndreyDyatlov 7 місяців тому +5

    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.

  • @doseofted
    @doseofted 7 місяців тому +1

    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.

  • @josevsebastian2909
    @josevsebastian2909 7 місяців тому +1

    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.

    • @jherr
      @jherr  7 місяців тому +3

      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. 😂

  • @aftercamp4322
    @aftercamp4322 7 місяців тому +1

    5:06 What plugin should I use to highlight my code?

    • @jherr
      @jherr  7 місяців тому +2

      I don't use a plugin. I use screenFlow to do the highlighting.

  • @matterhart
    @matterhart 7 місяців тому

    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).

  • @Michael-Martell
    @Michael-Martell 7 місяців тому +1

    I’m struggling with env variables. With the split in Serverside / client side, it doesn’t seem to want to pull the env variable.

    • @zombiefacesupreme
      @zombiefacesupreme 7 місяців тому

      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"?

    • @Michael-Martell
      @Michael-Martell 7 місяців тому

      @@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?

    • @Michael-Martell
      @Michael-Martell 7 місяців тому

      @@zombiefacesupreme 16:03 this seems like what I’ll need to implement to get it to read the env variable I think?

    • @jherr
      @jherr  7 місяців тому

      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.

    • @Michael-Martell
      @Michael-Martell 7 місяців тому +1

      @@jherr that exposes the api key to the browser allowing malicious users to take the key and use it for their own right?

  • @Dylan_thebrand_slayer_Mulveiny
    @Dylan_thebrand_slayer_Mulveiny 7 місяців тому +1

    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.

  • @DavidSmith-ef4eh
    @DavidSmith-ef4eh 7 місяців тому +4

    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.

    • @nazarshvets7501
      @nazarshvets7501 7 місяців тому

      Only real usefull thing they did is nested router. Rest of features (caching, server-actions, RSC) is real barrier for migration to new router

  • @eero8879
    @eero8879 7 місяців тому

    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.

  • @devsadi
    @devsadi 7 місяців тому +2

    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.

    • @nazarshvets7501
      @nazarshvets7501 7 місяців тому

      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)

  • @andrewiglinski148
    @andrewiglinski148 6 місяців тому

    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.

  • @skapator
    @skapator 7 місяців тому

    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.

    • @jherr
      @jherr  7 місяців тому +1

      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.

    • @skapator
      @skapator 7 місяців тому

      @@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.

    • @jherr
      @jherr  7 місяців тому

      @@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.

    • @skapator
      @skapator 7 місяців тому

      @@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.

    • @jherr
      @jherr  7 місяців тому +1

      @@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.

  • @johnkucharsky6927
    @johnkucharsky6927 7 місяців тому +1

    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

  • @schintus
    @schintus 7 місяців тому +2

    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?

    • @NicolasSouthern
      @NicolasSouthern 7 місяців тому +1

      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).

    • @schintus
      @schintus 7 місяців тому

      @@NicolasSouthern Nice, Prisma + Zod sounds amazing.

    • @alexbecar977
      @alexbecar977 7 місяців тому +1

      ​@@schintusDon't get too excited, entity framework is miles ahead of these options.

    • @schintus
      @schintus 7 місяців тому

      ​@@alexbecar977IMHO Next/JS should never call a SQL server itself. It should call an external API (not NextJS APIs) to get its data 👌🏻

  • @mrfabulous3303
    @mrfabulous3303 4 місяці тому

    What browser are you using ?

    • @jherr
      @jherr  4 місяці тому

      Probably Arc.

  • @PeterParker-nh9di
    @PeterParker-nh9di 7 місяців тому +1

    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?

    • @jherr
      @jherr  7 місяців тому

      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.

    • @nyxandtyr
      @nyxandtyr 6 місяців тому

      @@jherr What do you mean by "you don't control the API"?

    • @jherr
      @jherr  6 місяців тому +1

      @@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

  • @k303k
    @k303k 6 місяців тому

    Will you make Nextjs14series pls sir?

  • @guidobit
    @guidobit 7 місяців тому +3

    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.

    • @bartoszkrawczyk4976
      @bartoszkrawczyk4976 7 місяців тому +2

      or error handling...

    • @oliversaxon8656
      @oliversaxon8656 7 місяців тому +3

      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.

    • @rockatanescu
      @rockatanescu 7 місяців тому

      @@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.

    • @dealloc
      @dealloc 7 місяців тому +4

      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.

    • @exactzero
      @exactzero 7 місяців тому

      How is that React's problem? Isn't that an issue in the backend as well if you don't validate and sanitize input?

  • @nyxandtyr
    @nyxandtyr 6 місяців тому

    oof. Clear as mud.

  • @airixxxx
    @airixxxx 7 місяців тому

    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.

  • @Zeilar
    @Zeilar 7 місяців тому +1

    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.

    • @rod6722
      @rod6722 7 місяців тому +2

      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.

    • @dealloc
      @dealloc 7 місяців тому

      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.

  • @jibreelkeddo7030
    @jibreelkeddo7030 3 місяці тому

    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
      @jherr  3 місяці тому

      Well, except that it is sanitized by @vercel/postgres.

    • @jibreelkeddo7030
      @jibreelkeddo7030 3 місяці тому

      @@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.

    • @jherr
      @jherr  3 місяці тому +1

      @@jibreelkeddo7030 Ah, fair, agreed.

  • @xxXAsuraXxx
    @xxXAsuraXxx 7 місяців тому

    Hope they revert everything and just fix react fundamental issue 🎉

    • @jherr
      @jherr  7 місяців тому +1

      What's React's fundamental issue?

    • @xxXAsuraXxx
      @xxXAsuraXxx 7 місяців тому

      @@jherr footguns, v-dom and react forget

    • @oscarljimenez5717
      @oscarljimenez5717 7 місяців тому

      @@xxXAsuraXxx so you want that React be like Vue or Svelte?

  • @laughAFrame
    @laughAFrame 7 місяців тому

    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
      @jherr  7 місяців тому

      Yeah, pages router was better for that, but even then some library components weren't SSR compatible either.

    • @laughAFrame
      @laughAFrame 7 місяців тому

      @@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 😑😑

  • @shadowfaxenator
    @shadowfaxenator 7 місяців тому +5

    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

    • @srymisclick
      @srymisclick 7 місяців тому

      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?

  • @yadusolparterre
    @yadusolparterre 7 місяців тому +1

    So in conclusion the best practice is not to use it 😂

  • @avsheshsavani6257
    @avsheshsavani6257 7 місяців тому +1

    1st view