The "SQL In React" Drama
Вставка
- Опубліковано 22 сер 2024
- I think we can all learn from this. Next/React, server actions, sql, "use server", I get why we're confused. Hopefully this clears up a lot of that confusion.
SOURCES
x.com/t3dotgg/...
x.com/tomdoes_...
x.com/AdamRack...
nextjs.org/blo...
Check out my Twitch, Twitter, Discord more at t3.gg
S/O Ph4se0n3 for the awesome edit 🙏
I think at the end of the day the big issue here is that pretending that the boundaries between server and client are completely arbitrary is just a lie. in 99% of situations, the server is on one machine in one physical location, and the client is in a different one, often separated by hundreds of miles and many network hops. This SQL in Component code pretends like the internet is the one giant monolith and that you can access any part of it from anywhere it, which is just patently false. Eventually, no matter how sweet the lie is, somebody is going to run into a use case, or situation where the real fact that there are two separate machines communicating with two separate sets of data and two separate permissions schemes, will conflict, and this giant house of cards will come tumbling down and they'll be stuck with their heads in their hands trying to debug 5+ years of idealistic client developer dreams
Well this has actually happened already.
So when dealing with dates and server side rendering there is an obvious problem. If you generate a date on server and then try to hydrate it on client then you get two slightly different dates because some time has passed between the two events. This results in a hydration error because the hydration needs the state to be the same between server and client.
The proposed fix by react team is to monkey patch the standard Date class which is a horrible idea imo. I'd much prefer if they just gave their own wrapper around Date instead of messing with the standard classes.
100%. No matter how many frameworks people get tricked into supporting, the scaffolding stays the same. If you only know the framework, and not the scaffolding, you have always built a house of cards.
Imagine that React has an unresolvable critical security flaw in it, or Primeagen becomes CTO of your company. You have to pull the framework, and 99% of your "engineers" are gone instantly because they know how to framework, not architect. It just takes one such instance and people are back to the old stuff, and the new guys aren't getting paid for that...
I think server side rendering in general is a mistake. The majority of end user devices are very fast at rendering web pages. It leaves all of that compute power entirely unutilized.
The last thing I want in my UI is for a backend change to cause a cascading affect throughout my application. In angular we separate out an api mapping layer specifically to handle server communication and map it to a front end contract so when a backend change is made only the mapper layer is affected the majority of the time.
I don't want my UI to be exposed to backend complexity. Nothing to do with "separation of concerns." Instead we are isolating and segregating the complexity of the two applications.
this is not fun, this is just php in new clothes
Modeselekting
Nothing wrong with PHP, but this also gives us types and LSP support inside our templates, which is missing in PHP templating languages, my ideal paradigm would be db to html in as least steps as possible + LSP in templates, this is really close, but I would prefer to do it in a BE first framework (GO keeps calling me to learn it), and do the client stuff with vanilla.js, the whole rerendering model is convenient for writing interactive stuff, but its bad in performing, its too much bloat served to the client for our convenience of writing state dependent UI's declaratively.
If you insist that literally everything about PHP is bad, because it relates to PHP, then you are the problem. You are not enlightened, you are ignorant.
In fact, in general, if you do not know how to advocate for both sides of a debate, you are uninformed about the side you do not know how to advocate for. This doesn't mean that you DO advocate for both sides, but you need to be familiar enough with both sides that you could, in theory, pretend to be both sides.. Because if you cannot, then you don't know what the other side's talking points _actually_ mean, even if you know the literal words they use.
No methodology approach. There is no server. There is no client. No need to separate. Just put everything in your page file and build up that technical debt.
method 1: need nothing but when over 10 lines put in own file 🤡
Please tell me this is satire... There is nothing about the example that is shared here that is good clean maintable code.
We did this for years in PHP, eventually realzied it was wrong. History repeating itself.
These hipsters just can’t help themselves….
We've come full circle back to PHP
This is what we used to do years ago with PHP and it was considered bad practice. Now you are telling me it's cool?
mix php with not composable markup was bad practice ofc HAHA
This is still not the best, because most of the time I'm confused what is client and what is server
You didn’t though this is setting up an rpc. I’m not saying it’s right but get your brain rot out of here
@@amogh708 That's a thing, I hope that with the new tools that comes these months that problem it's settled, you can learn though
It isn't what you used to do with PHP though. It's specifically different, which makes it different.
Well. All is fine, but in reality the backend is needed for non trivial projects. If y have 3 resources that Crud cool. But when you have Authentication, Authorization, RBACs, Sessions, Postgres + Caches, Stripe Subscription + Payments, Plans, SMS, Email Scheduling you typically need a robust backend. The problem with tutorials is real..
Did you watch til the end? You can do exactly what you stated. Separate concerns at will. The first demo was just to show one way of doing it and it was mentioned that this is NOT the recommended way for production projects. But it's a good way to write code when you just want to prototype something quickly.
Yeah but, until you have more than 5 users, none of that is needed.
And, no, it's not needed for a blog
Too "magic" for me
Thats why I only use assembly
@@deadchannel8431 assembly is magic too, do you really trust an "assembler"? Thats why I only directly write the machine code, just like von Neumann intended
(yes, really. Look up his stance on assemblers)
@@RepChrisyou’re using computers? Pathetic, I bang 2 rocks together like my ancestors did in the neolithic period
Just use remix then.
@@Adityacode To me "Just use Remix", for like 99% of people in the small group that actually needs strong SEO, the bloat of Next and it's "magic" will just impede them.
Web dev is a joke.
And I dislike frameworks that try to be too smart, and do magic behind the scenes.
This doesn't also teach you anything, because you have no clue what is going on, you are just a tech witch doctor.
If you’re building a pet project, separation of concerns is not as big of a deal. But can you imagine migrating to a different technology when there isn’t a nice separation? It’d be so much harder
This is why a strive for less dependencies, which admittedly is very difficult in Node land. The more abstraction you pour on top of everything, the more locked in you usually are.
I understand you and I properly disagree.
If you are designing something specifically to be migrated later, just writer it in the language that is its final destination the first time.
If someone 20 sprints from now wants to migrate it, it should be never be the dev that gets blamed for the fact there wasn’t a design choice to make it easier to migrate.
Do you see what I’m trying to say?
@@airkami changing technologies or refactoring code is quite common, and almost always without foresight. Maybe you have a new customers and therefore new requirements. Or scaling issues. Or maybe a product feature didn’t land well and you need to redesign.
One recent example that comes to mind is Uber moving from Postgres to MySql. Ain’t no way 20 sprints ago they said, “alright let’s implement it in Postgres, but ultimately we want MySql”. That’s asinine.
@@airkami No one is designing anything to be migrated later on, its just that in real world changes are bound to happen. You can not always predict the whole product specification and requirements from the first step and you might need to pivot at some point. You pretty much always need to pivot at some point if you have an actively developed product, the question is usually not if but when and how much.
The dev should be blamed for not accounting for the possibility of a pivot because any decent dev should know that they are bound to happen but the dev shouldnt be blamed for the lack of a full fledged migration case planning.
I really like Theo and his content but those "arbitrary boundaries" are not really that arbitrary, they are there for a reason. I dont suggest going crazy over very strict rules and making a very simple project a fragmanted mess in the name of separation of concerns but striving for those "boundaries" without losing sight of what and when you want to achieve something is the key imo.
People overthink this. Separation of concerns is frequently an exercise in futility. CSS and markup seperation for instance. 50% of the time beneficial and 50% detrimental depending on the project ie Apps vs Information sites. When structuring code, the lines of separation are also very arbitrary. For example, the vast majority of SPA's have a custom endpoint on a custom backen for a specific purpose that is so tightly coupled that it is really only useful from that one place it used in the frontend, but now it is split into two places. I separate based on future anticipated pain points. Sometimes a monolith makes sense. Sometimes a bunch of micro functions make sense.
The reason why I am against things like this is for a single reason. People will make abominations.
I've already worked in multiple codebases where people fetch, mutate and render data in a single file and has made things impossible to maintain.
Like old PHP
It has been done since the dawn of programming UIs. It will be done again.
e.g. PHP "templates"
How is it impossible to maintain?
If everything is in 1 file you can just modify whatever you need, it's very nice and straightforward
And if you need the same logic in multiple places you can always extract it into a common function and call it from whichever file needs it
@@pokefreak2112 You're essentially suggesting a rewrite and at the same time claiming it's maintainable. Do you see the issue?
Couldn't be web devs fighting over syntax instead of solving problems. This industry has done nothing in the past 10 years other than glue together stupid syntax and frameworks in 1000 different ways. It's not SQL in react server actions that is stupid. It's the entire industry, you all need to do some serious grass touching and realize I don't want to wait for 10 seconds for your bullshit code to draw a button. Web would work just fine with 95% less code, you have lost the plot.
Based
Yeah, I've been web developing since the late 90's and can attest that the problems we solve today are not much different from 25 years ago. Back then the tools were much simpler, now web tooling is like a fever dream. But they are all within the same basic paradigm: Read the data storage, template it into html, display. Receive user input, broadcast to server, save to data storage. Over-engineering and the pursuit of 'hip' tooling prevents web development from ever leaving its adolescence.
You will wait for 10 or more seconds because the business wants SPA and all this beautiful interactive stuff. We have a lot of light frameworks of meta frameworks, but businesses are more interested in heavy SPA
this is completely based... web has gotten a lot better, websites got significantly faster in the last years with better UX/UI and easier to build just because of the advance of technologies like react.js,next.js and its competitors
My problem with these tag literal functions is that they always *look* like the wrong thing. Like, we have spend years training people to be afraid of exactly this kind of string, and now we make a syntax that makes that OK.
I'm not saying taking the obvious naive solution and just making it work and making it safe is bad, but that it comes build in with disgust and fear around it, and such a reaction to it is perfectly understandable and predictable.
Same might go for the use-server stuff. I have seen beginners in PHP confused why they can't run their PHP code when someone clicks a button. It's a classic beginners trap. So now these people learned "the proper" way this works and when they see code with "use server" that they assume it's just uneducated, or subconciously get mad at it because they had to learn all this other stuff.
Yep. Accidentally add some brackets around this and it's vulnerable to injection. Makes it much harder to catch mistakes like this if the "correct" way looks the same at first glance.
@@SwoopWoW I hope the devs have thought of that and calling the sql function with 1 string argument (when template functions requires the 1st argument to be an array, and 2...N args are any type, or they may not exist) will yield an error or something... preferably even before running the code, e.g. highlight it as an error in the IDE.
Doesn't sound like a problem at all. If someone is writing an app using a stack that generates server code, they have more than enough capacity to understand what is happening. New users have to learn all kinds of things. It's not like you could drop this in a random HTML script tags and accidentally nuke your DB. It doesn't point anywhere without the compiler.
Well perhaps we should have "spent years" teaching developers WHY writing SQL with concatenated variables is bad, as opposed to teching them to be afraid of seeing SQL.
@@MrManafon That's not the point. They know why concatenated SQL is bad. That's why it causes issues when you introduce a syntax that looks exactly like concatenated SQL.
"use server" acts wayyy too much like a magic word/phrase. is there no other more pleasant way to wrap the functionality?
Kind of remind me the old "runat=server" attribute for asp (?)
solidstart used to have a server function macro which was a lot better in my opinion. they switched over to "use server" not that long ago unfortunately.
I think the problem is that React used to be a framework with very less magical things, and that is why it's popular.
and now it become hey this mark mean this and this
First thing I would think of when seeing SQL inside of a client-component would be "Oh, nice, they probably use some kind of compiler or what not to replace the sql with a fetch call on the client and generate a corresponding REST endpoint on the server".
The only thing I would be wondering how it's done is authentication in this case, but otherwise it looks really nice. I always found it frustrating to do a bit of frontend, then a bit of backend to check if everything works, debug both and repeat. I hate it when I have to switch between the two, because when you can focus just on a single thing, you get into a deeper state of focus and it just goes faster.
Yes, this is what I want to see, authentication and some security mechanics when using this approach.
wait wait why would anyone do that? if something like that is gonna be compiled away anyway to REST endpoint ?
you can access the request header and cookie inside the server action to do authentication and authorization, they basically recommend to treat server action like a public facing api.
It's not the sql call that is transformed, its the call site of the action within client components. The action will be placed in the server bundle, then the call in client components will be transformed to an endpoint (actions are executed based on their ID from the same queue). Your sql call will stay as-is on the server-side.
@@dealloc You just said that I'm both right and wrong..?
Watched the whole video and am even more concerned. Mainly, how can you enforce authentication and per-endpoint authorisation (or even something like Role Based Authorisation)? Also, everything posting back to the root directory of the site seems like an analytics nightmare, no? For example, how would I go about investigating the API surface for issues? Please reply if you have answers.
It looks like another abstraction layer is needed. Theo created only data abstraction layer, but to have per-endpoint authorisation another layer will be needed, like controller/presenter layer, which will check that current user actually has rights to access this resource.
So final code will look something like:
formAction={async() {
"use server";
await UserPresenter.deleteUser(id);
}}
const UserPresenter = {
deleteUser(id) {
const currentUser = await getCurrentUser();
if (hasPermissons(currentUser)) {
await DL.deleteUser(id);
}
}
}
do these in the server action. Basically your auth your user before the db part is fired. If the user isn't allowed to do the thing you return an error
Reminds me of linq, but my problem with it is it's not terribly clear where everything is happening. The framework is doing a bit to much work.
"a bit" :D :D
Idk I like dotnet a lot. You can also always inspect what kind of queries are ran by LINQ.
the crazy part is when you use "use client" and the component is still rendered on the server initially
I'm curious. If your goal for your project was to also make an API that is consumable for 3rd parties, would you also just make an API layer which exposes your DL object (in this example), and then in your main application use all the server component stuff for the nice usage pattern (among other things)? Or would you approach it a more like how you would before server components were a thing.
I find myself still wondering about that as in my current job a lot of the projects that we make / maintain are designed for 3rd party integration. I would really like to start using this, but haven't quite wrapped my head around how you would handle a scenario like this.
You'd probably go api first and someone or team take care of api since api will now have to be documented, maintained and enhanced as requirements dictate and evolve. The api becomes it's own living project with challenges and complexities.
If you are creating a 3rd party API, why you even use Next.js?
@@drosi1994 maybe recency effect and his brain has freshly cashed knowledge on next js backend stuff. Why would you pick and not pick next?
@@drosi1994 We are not yet. I'm evaluating options for a project that we are starting in a few months. I'd like to be able to use RSC because the pattern seems cool and would work well for the first party UI of the application, but the requirement of having the API accessable by 3rd parties is my sticking point
@@Mr_Simmons I think it's going with the api approach and consuming the api is your best option. This is because doing rsc would effectively duplicate data calls. But I believe you can still consume your own api using rsc. You will have to build your api either ways for the consumption of external parties. Dog food the api by consuming it yourself. That way you see also validating the api. But what weighs more in making the project successful? Third parties consuming your api or your internal use?
.net and specifically ef core has something similar. SQL injection had been so well publicized and understood most frameworks will probably automatically handle interpretations.
Yeah, but the EF core framework is specifically to deal with SQL ORM - this is just some straight SQL bang in your react code.
wym? do they use a custom InterpolatedStringHandler?
Supabase capitalises on this a lot. Taking advantage of the server side, feeding into the component.
It's made my most recent projects so much smoother and cleaner when working on them.
What happens if you want to add middleware to a server action to ensure the user is authenticated etc?
more react code spaghetti that's for sure.
What do you mean? The middleware would just be a function.
@@underflowexception remix generates a request handler, which is generic enough to be used in express, cf workers, lambdas, etc. Add your middleware to your favourite server lib, run remix on top of that.
there's nothing you can say to me, when i see that "use server" i will ALWAYS cringe
Is it because things are rendered on server by default? sry if it's dumb I don't use next js
Edit : ah mb I continued watching the video
“use strict”
That's the best part, you don't have to use it if you don't like it. It just gives us another option to compose how we want
You seem to think that people care about how you feel about this.
@@lyovson well you seem to be offended, who knows why
I honestly just think the choice to make a magic "use server" string to tag this kind of thing was a huge mistake, and is always going to look awful to a lot of people.
I don't understand why it isn't some form of wrapper tage that surrounds the server action instead. It just feels like a gross hack.
A “wrapper” would be describing different compiler behaviors via an import, that sounds much worse to me
Feels like I've lost my very personal battle agains the "fullstack" title. In my experience, what fullstack ends up meaning, is a decent front end developer and an ok backend developer. Separation of concern is about more than clean code. IMO it's about making it clear to stakeholders (and junior devs) that moden tech is not a one-skill-does-all thing. You'll need experts. And the more those patterns are broken, the more debt you gather for the day you need to scale just slightly.
On that note, so much of the new things in JS libs are dons just because they are cool, and would work perfectly for small singular dev projects. There is a use case for them, for sure. But I think JS influencers should talk more about how you would actually want to do things when you're working with ten teams of 8 developers, in 15 repos and 10 different apps :)
Code should never feel "magical" it should always be reasonably easy to understand.
If code is feeling "magical" it just means there are too many abstractions going on that will make it easy to shoot yourself in the foot.
This pattern is cool for sure but I haven't seen any real apps using it to actually believe it. Like I have so many questions right now about auth, security etc.
In the old good days when PHP had PHP, HTML, JS and SQL in 1 file, we called it spaghetti code and were rewriting, or just burning it. Nowadays people writing JS, HTML, SQL, CSS in 1 place and call it "thats so cool"... I hope server side rendering will come back because it's not even funny anymore...
I would recommend everyone to never write sql in react. I have seen the same in PHP and other frameworks. It's not the way.
Having a 3000 line component in 5 different languages is not the way.
@@JeremyAndersonBoisebecause this is a trivial example, but we all know that's what ends up happening
Then what's the way?? Also 3000 line components is really bad. Sign of a horrible code. Basically what I do in server component is fetch the data and pass along to other component. That component can be client or server depending on use case.
You can always split the component into multiple files. Even if multiple components wants the data just pull out the data call into separate file and use cache functiion, the cache function ensures that it is run only once.
@@heyjitendra Yea I think we completely agree. There needs to be some basic separation.
I was just saying in the previous comment that I have seen what having no separation leads to.
I have literally seen files in PHP where it starts with html, then some PHP functions, then some SQL, then CSS, then back to html, then javascript functions, etc. And it's sprinkled like that in no order in the entire file switching between 5 languages.
How do I understand the API surface of my app? Oh that's easy! just go through every file and UI component and pick through the JSX for magic strings
Or... you watch the video for long enough to realise he suggested a solution for that: having a data access layer, where you abstract away the DB functions in their own file/folder and call them in your server actions.
But better question: Why do you want to understand the API surface of your app anyway?
APIs, for us web devs, are just a means to an end, to get DB stuff or Auth to run on the server. It's only so that our UI can work. The only time you'd need to worry about your whole API like you suggest is if you made a public-facing API, but you'd obviously not use this pattern for that.
Most apps are being built to serve some kind of frontend, so if you wana see what the "api surface area" is, just go to where it's being displayed it can't really get any clearer tbh.
Well, if you wanted an API you should really consider building an API.
Do you laugh at racing cars because they don't have pickup beds? Do you insist that all buildings should be built from the same materials?
@@chipmo if you're building some website, the API is all publicly available endpoints whether they were designed or not.
From both a security and maintenance standpoint, obscuring the API by embedding it in UI components is a complete nightmare
@@robertlenders8755 The amount of security/DX/UX issues caused by creating an API layer just to serve a frontend is the exact reason these new patterns exist. Having an API doesn't equal good security and maintenance, having a good a setup and good practices ensures that, there's no reason this cant be achieved by "embedding" it in the UI, just abstract the functions to an "API" folder and structure however you like, and you've got the exact setup an API could have, but just without the crappy network code. so much cleaner.
Are these form elements secure against custom POSTs? What I mean: let's say i have some business logic which checks if a user should be able to delete something, is it sufficient to just not provide the form elements for that user, since the endpoints use encrypted data? Is the encryption key different between sessions? That would be awesome
the little sql string template is so easy to miss, and it will still work without it
1:10 in; I have virtually no real-world experience with React, and I'm mostly working in dotnet and Angular... and I immediately see the 'sql' before the literal template and realized React created some sort of interpolated string generator that parametrizes and sanitizes the values it's inferring.
But I'm also curious why a much more portable service-layer isn't being used... code like this is fine for rapid application development, but it's kinda grinding against the standards and norms of enterprise code.
Can you elaborated on the standards and norms. I've tried. DotNet a few times and it boggles me to infinity the amount of configuration and intermediate stuff the must be setup just to get some things working. Did DotNet /enterprise become that way because of things like regulations and traceability?
@@elmalleable
Yea, pretty much. It's so traceable that it has a ILogger interface baked into it that you can leverage with any number of "Factory" solutions (NLog, Serilog, etc)
It's written that way so you can flip out modules, components, libraries at-will even if very few teams ever make use of that flexibility.
---
... so. .NET implies .NET Framework; which is 4.8.1 and earlier; this is what WinForms and MVC 3/4 were most likely written in.
When you see 'dotnet' written out like that it's implying it's dotnet core; so effectively dotnet 5/6/8 (usually whatever the LTS version is at that point in time).
.NET Framework = 80% configuration
dotnet 8, one file of dependency injection and configuration, the rest is code.
At the end of the day dotnet is all about rapid application development on enterprise solutions, so it needs to be durable but also dynamic enough to handle oddities/nuance that business logic dictates.
It's meant to be written with "do not repeat yourself" in mind, but "enterprisey" code is also supposed to be written in silos, meaning THIS branch of logic shouldn't effect THAT branch of logic directly.
That's why most modern dotnet is going towards CQRS and/or Mediator Patterns where you can just write hot-swappable micro-services that simply move data around to conduct individual pieces of business logic.
@@elmalleable It's more that Microsoft products and their ecosystem are just very well suited to large organisations. Doesn't matter if the dev experience sucks, they're not the ones making the decisions on what to use.
Everyday we are reaching closer and closer to PHP
With the button example at 5:50 - what does the POST request look like? URL and body
ah, shown at 21:13 - the form has hidden input fields with encrypted data, those values are POST'd in FormData to `/`
Am I not getting it? Because this looks completely ridiculous to me.
Why would you want to so something like this? Why?! Whether it is secure or not comes after.
_Modern_ web development is just broken. Do any modern web devs actually know what their code does? In any meaningful way?
Does anybody even know even a single spec? I believe the answer is _no_.
yes you are not getting it. the idea is that you don't need a bunch of files and a separated BE, you can have the same functionality of a full stack application with a lot less boilerplate and code writing - while maintaining separation of concerns and security
one "issue" i see is that you might end up writing a client function which calls multiple server functions, maybe even in a loop, and it might not necessarily be obvious that you are calling a server function, resulting in an excessive amount of requests being sent to the backend
although that is probably something that can be easily cought by a linter (calling multiple server actions from a client function => fix: turn this into a server action instead)
But whether it's a function or whether it's an api call, you still are running the risk of sending many requests? so to me it doesnt seem any different - other than the fact you dont have to wire up a network call anymore, so long REST/gql :D
@@jackjsy From what i read in the docs you can just call the server actions as normal functions inside a server function, which means that instead of sending out 20 requests form the client to the server, you would just call the function 20 times serverside
Also even if those 20 calls weren't other server functions but actual requests, if those requests are sent to your service infrastructure, sending them from inside the cluster will have almost 0 latency
And then there's also ratelimiting which might get triggered with smth like that :D
It's not a massive issue, but i think one of the only "fair" criticisms i can come up with for this "pattern"
@@dahahaka Fair points!
Are they going the PHP way? 🤔
React is PHP way. Angular is java way
It always was the PHP way.
It is PHP all the way down. Always.
What that fuck r doing the dev community SSR -> SPA -> SSR
Even though I enjoy seeing boundaries being pushed, I still don’t know why the way it is today is not the way 😅 is it just me that likes having two different codebases (even with different technologies and languages) to handle frontend and backend separately? It’s not even about the separation of concerns to me, it’s more about not wanting to use JavaScript more than I have to
Theo explaining how code works are the best videos IMO
And does the static generation work when using SQL? For fetch calls, you could tag every request, set the cache and revalidate it, but with SQL calls I don't see the option
This SQL drama's cool but where'd ya get that shirt??
I love the thumbail with the sql injection security problem. That look and the sql injection was just a chef's kiss.
E: that is cool and i totally forgot about that usage. I would never use that usage since i want to ensure explicit control along with function comprehension. Which is why i ignored it completely and forgot it existed. The day someone removes sql from the beginning and i have to use my tools is the day i remove it from the codebase completely.
I raised this at work and their reactions were of the charts 🤣🤣 how it's soooo unsafe lol.
I told him the only way this is not safe is if you have a developer that's gone rogue lol
SQL in your front-end code?
*Ancient PHP programmer enters the chat*
🤣
but acktchually php era the Frontend is backend code eh?
🤣
Nice endpoint security. Now you don't even know where the endpoint is.
Hacking websites in 2030 is going to be a piece of cake.
I think we only have the discussion because of the example using directly sql in the react component. If the example used a data access layer I'm pretty sure no one would have complained
We are back to php 2006 and htmlspecialchars
Watching Theo reinvent basic concepts in this frankenstein's monster-esque trainwreck of a system (server components) has truly cursed my eyes.
The moment I could feel the last of my sanity drain from my brain was at 12:43 where he reinvents the concept of a basic service class used in almost every good backend framework that has dependency injection on the planet.
Just dont do this man, it sure seems neat, and nice, - so cozy to wrap up all the code backend and frontend in '1 framework' but when you put the cards down for any project requiring maintenance, bugfixes, support, etc - this approach will only lead to a bloated, convoluted, spaghetti bolognaise of a codebase - as soon as the application needs to handle even the barest minimums of complexity - as most applications of any real use have to.
I guess if you want a highly opinionated approach, where the opinion is objectively wrong for 95% of use cases, go with this approach. Oh and i hope your pentesters are good - in a more complex codebase you're practically guaranteed to have at least one critical security issue caused by developer error - in the same way you'd have a car crash by driver error if the road was made out of ice, coated in oil, and covered in a thick layer of fog that prevents vision more than 2m in front of you.
Maybe you should actually step back a bit and try to understand what this does because i don't think you do 😅 and i say that as someone who themselves doesn't really like using js on the backend
Theo is a react Andy these nerds literally don’t know what their missing on with rails & Hotwire or laravel or phoenix liveview …
why do you think his data layer pattern is that bad compared to a more standard backend? honest question
It’s not security that’s the problem. It’s that you’re coupling all the way through your application layers, basically guaranteeing that your dev speed will crawl to a standstill in a years time when your architecture crumbles beneath the weight of change requests.
I feel like he addresses in multiple parts of the video. He lays out how you can separate concerns
Either edit it in one place, or edit 5 files like we do currently. Not sure why you think this is more work than now when underlying architecture changes. Seems more DRY to me
All you've done is separated React into client and server libraries. How is that not separating concerns?
It is
It's separated in functionality, not separated in files/code. Your server needs can live right next to the client needs. However I feel like this just makes things less straight forward to address in the future. I'd rather them be more separate so I can address them separately as needed.
@@FrostbytedigitalI tend to agree. I have API services that operate as a backend to multiple different clients, and having all of these in React doesn't seem to be a particularly good solution to me. On top of that, this seems like an abstraction over the communication that's actually taking place and that seems like a really easy way to shoot yourself in the foot.
2:20 - don't do this. This is isn't modern. This is as old school as PHP projects (or Java JSP/JSF) that mixed templates with code and SQL queries that everyone makes fun of nowadays and dreads projects like that. Modern web dev people reinventing the wheel again and repeating old mistakes.
Maybe try watching the video til the end...
I do implement all my recent projects since stable server actions this way, have my plain typescript service functions organised, use it directly on server components, and when if external clients needs api, just create api routes end expose thoses exact service functions.
Not only it makes code more cleaner, it's really fast to implement.
What i like the most is switch from ORM or any database and external services easy..
So are tag functions in React the equivalent of Dapper parameterized queries in .NET?
Glad you liked the memes :)
can't wait for react to backpedal and say that this was their most horrible idea ever.
Couldn't agree more.
Wasn't some time while back someone exposed the "secrets" in nextjs because of this "use-server" shit ?? I think theo covered it too.
I don't agree. The future lies in server + client combo. The components that do not require client interactivity will be rendered on server and the rest on client. Super slick combo
@@rampandey191your comment is a bit ambiguous.
@@rampandey191What future lmao. You soydevs are funny trying to spin decade old paradigms as something new that JS is doing.
@@nou4605 The old paradigms of the past only had server side rendering and not client side rendering. For client side rendering they had to use jquery which is a different ecosystem with its own set of problems. While in react everything is react no need to leave the ecosystem. This is very different from the past. Please understand things rather than copy pasting things from twitter.
We r getting SQL injection with this one 🔥🔥🔥🔥
The DAL (we call this DAO in Java on the server side) is exactly how code is structured at $work. We do this so that we can have a services (microservices) with defined contracts that multiple front end applications can use. As long as we maintain the contract, no one cares how we provide the information. If a new application needs something similar but different, we can make a v2 of the service. Then other v1 service consumers can migrate when ready (or not).
I can definitely see an advantage of making a component-based structure for API / service accesses that are unique to a particular application. Going through extra hoops "just because" engenders lots of extra code to maintain.
However, if not done correctly, clarity and maintenance become challenges. This is where a well-designed DAL (like you are doing when I paused the video) is key. This enables developers new to the code base to find, fix, and extend an application with less chance of breakage.
And as we all know, the cost of an application is not in its creation, but in its maintenance. And developer burnout is increased by being shackled to a code base that only that particular developer understands.
I might be wrong, but it seems like this too much flexibility will require us to make more difficult decisions which could be time consuming. RestAPI might take a bit long to code, but it's simple. We don't have to spend time thinking how to implement it.
Another issue with server actions is transportability between react web and react native, if you're multi-platform. A more SPA approach to begin with is much more translatable to a mobile app / React Native
We have come full circle, god dammit.
If the template function ends up using prepared statements, I think it's fine. If it uses bog-standard sanitization, I think that's still an attack surface. Using prepared statements moves the issue into the database library itself. Using sanitization keeps the issue in front of the library, inside your sanitization logic. All it takes is one single case that you didn't think about to get past the sanitization layer, and you have SQL injection.
Prepared statements avoid SQL injection entirely. As long as it's using those, I think it's ok.
Broe I woud do this in my side project, get the job done quicker and learner.
I think it is either
1. sanitized, then it is just a syntactic sugar that why not just call the actual JS function instead of using seemingly SQL syntax which is only a false impression. Embedding another language is ALWAYS more demanding in terms of tooling such as linters. You code formatter and linter and conventions multiplies into exponential complexity.
2. Not sanitized, then it is security issue.
There is absolutely no win here.
This is just fucking plain old PHP over and over again
Backend developers * trying to split everything into microservices, use onion architecture etc *
Frontend devs - Let's try to write everything in a "single" file.
Some folks are claiming too many server actions can block the UI. Is this why we useOptimistic liberally?
5:59 how do you specify that endpoint requires authentication or permissions?
i hate server components. if you really needed that slight speed up in load time at the cost of server CPU load, go use jinja instead. i dont imagine the JS bundle required for client components was ever large enough to be an issue. isnt the main load time images that arent properly lazy loaded?
"Use Server" means => Use this block only on the server
I feel like this would only be maintainable for smaller projects.
horrible pattern .. we’re back in 1990s
Damn, not sure what direction I feel about this - on one side it's really nice to now have to write API endpoint on the backend, add the front-end version of that and do all the boilerplate code to make things work, just mark a function as "use server" instead and be done with it. On the other side it does seem like it can get messy quite fast, especially on bigger applications.
Wrote a quick test using next's where the server function just reads a text file and returns the content, and it is quite a nifty way of doing things.
this react SQL query is a very clean abstraction . It all depends on the devs how good and bad they are in managing abstractions. There are no rules but good designs - which is simple to understand and easy to apply / decipher
This is going to create massive problems. I never want client and server code in the same file. I don't want some implicit endpoint created by a couple lines in my client side js code. Who asked for this? What problem is this solving?
11:23 see, this is exactly the issue. I don't want to have to worry about server-side stuff accidentally bleeding into the client-side. It shouldn't be possible at all, no matter if I make a silly mistake or not.
I think I can appreciate the fact that he is defending the pattern by saying that it is "magical", and that a lot of parts are very very confusing. And that is probably my biggest issue with this pattern, I think separation of concern allow the clearly express your intent, not mentioning the benefits of focus mostly on what you should be concerned about, and not care about backend stuff that you should consider as abstraction. Because as long as SQL has been around, it is not the only player in town anymore and I feel like abstraction erasure will either prevent improvement because backend change would mean modifying a large mass of code that has a lot of stakeholders, or either block frontend change because those generated endpoint are being used by other unrelated clients.
Meaning as it is this would probably be a great pattern to obfuscate your code.
My only complaint here, is doing SQL and web UI formatting in the same object and the same function. I would probably make homefeed either make or accept a PostRepository, that has the methods to query posts. Then i can ship in a mock repo instead to test behaviors with the data.
We have two chairs: frontenders who want to use SQL in their components and backenders who avoid JS in client applications by replacing it with WASM
Not really, this just feels too much like magic.
most of the wasm frameworks are based on js frameworks. leptos is a clone of solid/solidstart with colocated server functions. dioxus also has server functions. the main benefit is server side performance, not necessarily dx on the client. although in my opinion, the dx is better but that's subjective.
yout state two things that are not congruent... that the string text is separated and is therefore sanitized and it is trivial to write into the function the methods to sanitize. So, out of the box, is it sanitized or just Schrodinger's cat waiting for you to notice that it isn't?
The problem is JavaScript
Is that Poimandres Storm or normal theme?
This would be a revolution, but in in the 10+ year NextJS tradition it shipped in a horrible state, with tons of bugs and inconsistencies. The whole thing where this ships with React 19 features, where React 19 is not out yet, it's just such a mess...
Many early adaptors are just going to bounce of it, and leave horror stories online for people. You are doing good work by clearing up lies, and when the AppRouter and server-actions/components are going to be ready in Next16, you will be able to say 'I told you so'.
You keep saying that the input parameters to the SQL _are_ sanitized, but I don't think that's really anyone's main issue, per se. At least, not directly.
One of the key things about parameterized queries that make them so powerful, is that they can be sent to the database server _without sending any data_ - that is, you can send the query without the parameters, and the database can optimize that query, and then you can send a bunch of different sets of data _after_ that without having to send the whole query again. This doesn't _just_ prevent SQL injection attacks, it _also_ allows for very fast and efficient use of the database.
In this video, you show that the query gets broken up into multiple strings, and the parameters are stored separately... But that's not the issue. The issue is that you then say that those parameters can be sanitized before being sent to the database. *That's* what _I_ have an issue with. The web server code shouldn't be doing that. It's not it's job. The entire idea of sanitizing inputs _should not_ be used, except for things like making sure the input isn't too long or really is a number when a number is expected, etc. For anything related to SQL injection, just make sure the query is *properly* parameterized.
I don't see any evidence that proper parameterization is being used, and _that's_ the real issue here.
It's very tempting for me to complain about your use of an ORM, but I'll refrain. My problem with ORMs are mostly just personal to me specifically, because my brain has a harder time thinking in terms of objects than it does thinking in terms of SQL queries, so ORMs are simply always going to give me problems, and it's not your fault you're normal. Besides, you already said the ORM approach is optional and isn't even necessarily what you'd always use, so it's fine.
Also, just a note: another term is 'prepared statements'. Depending on who you ask, either 'parameterized queries' and 'prepared statements' are the exact same thing, or the latter is the one I describe above and the former is just the same sort of thing but without the ability to reuse the query with different data multiple times.
I've used libraries that just stuck to the first phrase for both, others that used the second phrase for both, and at one time I _think_ I remember a situation where there was two separate libraries, one for each type, and so it kinda seemed like they were treated separately but really it was two unrelated libraries for the same language?
It's been a while and I don't remember exactly now.
As long as you can quickly unit test without having to load up an entire system
For multiple clients the backend api makes sense. For site only I don't need them
I think a lot of the people hating on server components and server actions 1) haven't taken the time to learn how to use them, and 2) have difficulty understanding when to and when not to use the features they enable.
Making certain things easier and opening up possibilities is a good thing, at least in this case. A little CRUD app probably doesn't need a separate dedicated backend, or an API, or microservices. If you're working at a large company with lots of separate teams, and need different types of system integrations, and have established technologies in place, maybe it's not smart to choose a full-stack framework like Next and implement everything through server actions. And for a greenfield web project, maybe it doesn't make sense to over-architect at the beginning, but instead use Next and server actions to get something simple and usable out fast.
The different technologies themselves aren't GOOD or BAD, they're just more or less suited to different situations based on the needs of the project.
For bigger projects I still prefer react query. It's amazing and you can also prefetch on the server 😊
5:03 I think the fact that it isn’t obvious that it is doing some sort of query parameteristation and sanitising is problematic. Sue I question one you know it’s tagged with the sql at the front maybe…. But I can see how it causes a certain kind of habit which could devs could easily mistakenly use in incorrect ways and accidentally introduce vulnerabilities. It’d be quite easy to skip introduced vulnerabilities in PRs too. Maybe it’s convenient, but it looks fraught with long term problems.
My thoughts:
1. The database model is visible on the front end. All sorts of wrong. Don't give the bad guys this information for free ! No matter how secure this is, just making it visible is waving a red rag to a bull where script kiddies and hackers are concerned.
2. If you need to do any kind of classic application performance scaling such as sharding or caching, the front end code needs to change - whereas the classic back end abstraction via an API keeps that hidden from the client side.
3. Puts the need for SQL skils and query optimization onto the front-end developer. YMMV as to whether that's appropriate.
4. RBAC again impacts front and back end.
It really depends on the context as to whether its appropriate. Where I work (supplier to BIG Telecoms companies) this would be an immediate no. Hobbyist pet project, no issues. It will be interesting to see where the line between those ends up.
The database model is *not* visible on the front end 😅 just an object that take in an id and a name
You clearly didn't understand how it works or didn't watch the video til the end
What is not fine is the same as anyway you code, just validate your data before touching the db. What I wish Next can do is have a way to specify server actions so that we can build a backend compatible with it.
Not starting this with an off-key "Oops I did it again" is one of the worst misses of the modern age
Imagine being mad about this.
Separation of concerns people are right in this case and definitely should NOT "shut up". The problem is the so-called "modern" stack. It's a broken bunch of components that won the popularity contests rather than being selected for architectural advantage. And thus the "modern" stack circles the drain looking for solutions to the very problems this popularity contest has caused.
I don’t get why people freak out a lot, they added an option, If you wanna use it, go ahead, no one’s forcing you to fuckin rewrite your codebase again just to use this, if you already have an API, then why are y’all getting so mad, not everyone is making the next Facebook, and if you’re doing it you may already know that certain patterns are just unmanteinable, and the other way around too, if you’re doing a simple ass project you don’t need to fucking add a lot of services and clean code, if straight SQL “in your fronted” makes your business run, do it and don’t bitch about by others tendencies.
I am not sure it's has been handled by react team or not during design server action, here is the scenario: let say a server action in button on click, it's already in production for a week and then we update the implementation by adding something or refactor the button then deploy it.
What happens to users that still use old version clicking the button with server action? It's used old logic or new logic or not found because the hash is changed..
Skew protection is pretty cool :)
For small projects this is totally fine, however for reusing/scaling/3rd integrations it can't be used. Also this next js hype is just keeping junior devs being junior devs.
remember when everybody hated PHP because you had spaghetti code in it with all those mysql_execute calls and then somebody thought it was a better idea just to have javascript on the frontend and javascript on the backend to avoid mixing the two?
Well.... then NextJS came in and became PHP but worse, worse performance, worse libraries, worse frameworks, worse environment.... let's just return to monke and use php with jquery, things were much simpler back then
Yea, trying to learn modern frontend stuff being backend dev, and it just feels like reinvented wheels everywhere... It's so much easier and faster to make this with PHP frameworks, or Django/Rails, and performance wise - good old admin dashboard can bring SPA to unusable state. And this is old days of PHP4-PHP5 templates days, history rolls backwards... Unfortunately job market needs JS/fullstack devs nowadays, so we will need to handle SQL in templates again.
All those boundaries are arbitrary, "said every JS/TS library ever ".