React Server Components always felt uncomfortable to me because they make it hard to look at a piece of JavaScript code and derive which parts of it are going to run on the client and which parts will run on the server.
It turns out this introduces another problem too: in order to get that to work you need to implement some kind of DEEP serialization RPC mechanism - which is kind of opaque to the developer and, as we've recently seen, is a risky spot in terms of potential security vulnerabilities.
I was a fan of NextJS in the pages router era. You knew exactly where the line was between server and client code and it was pretty easy to keep track of that. Then I've began a new project and wanted to try out app router and I hated it. So many (to me common things) where just not possible because the code can run in the client and on the server so Headers might not always be available and it was just pure confusion whats running where.
I think we (the Next.js user community) need to organize and either convince Vercel to announce official support of the Pages router forever (or at least indefinitely, and stop posturing it as a deprecated-ish thing), or else fork Next.js and maintain the stable version of it that so many of us enjoyed. Every time Next comes up I see a ton of comments like this, everyone I talk to says this, and I almost never hear anyone say they like the App Router (and this is a pretty contrarian site, so if they existed I’d expect to see them here).
I would highly recommend just checking out TanStack Router/Start instead. It fills a different niche, with a slightly different approach, that the Next.js app router just hasn't prioritized enabling anymore.
What app router has become has its ideal uses, but if you explicitly preferred the DX of the pages router, you might enjoy TanStack Router/Start even more.
I've been using React since its initial release; I think both RSC and App Router are great, and things are better than ever.
It's the first stack that allows me to avoid REST or GraphQL endpoints by default, which was the main source of frontend overhead before RSC. Previously I had to make choices on how to organize API, which GraphQL client to choose (and none of them are perfect), how to optimize routes and waterfalls, etc. Now I just write exactly what I mean, with the very minimal set of external helper libs (nuqs and next-safe-action), and the framework matches my mental model of where I want to get very well.
Anti-React and anti-Next.js bias on HN is something that confuses me a lot; for many other topics here I feel pretty aligned with the crowd opinion on things, but not on this.
Some of the anti-next might be from things like solid-start and tanstack-start existing, which can do similar things but without the whole "you've used state without marking as a client component thus I will stop everything" factor of nextjs.
Not to mention the whole middleware and being able to access the incoming request wherever you like.
I pretty much dumped a side project that was using next over the new router. It's so much more convoluted, way too many limitations. Who even really wants to make database queries in front end code? That's sketchy as heck.
This is what I asked my small dev team after I recently joined and saw that we were using Next for the product — do we know how this works? Do we have even a partial mental model of what's happening? The answers were sadly, pretty obvious. It was hard enough to get people to understand how hooks worked when they were introduced, but the newer Next versions seem even more difficult to grok.
I do respect the things React + Next team is trying to accomplish and it does feel like magic when it works but I find myself caring more and more about predictability when working with a team and with every major version of Next + React, that aspect seems to be drifting further and further away.
Yeah. Being able to write code that's polymorphic between server and client is great, but it needs to be explicit and checked rather than invisible and magic. I see an analogy with e.g. code that can operate on many different types: it's a great feature, but really you want a generics feature where you can control which types which pieces of code operate on, not a completely untyped language.
I had this issue with a React app I inherited, there was a .env with credentials, and I couldn't figure out whether it was being read from the frontend or the backend.
So I ran a static analysis (grep) on the apk generated and
Why would you have anything for the backend in an APK? Wouldnt that be an app, that by definition runs on the client?
Most frameworks also by default block ALL environment variables on the client side unless the name is preceded by something specific, like NEXT_PUBLIC_*
I remember when the point of an SPA was to not have all these elaborate conversations with the server. Just "here's the whole app, now only ask me for raw data."
It's funny (in a "wtf" sort of way) how in C# right now, the new hotness Microsoft is pushing is Blazor Server, which is basically old-school .aspx Web Forms but with websockets instead of full page reloads.
Every action, every button click, basically every input is sent to the server, and the changed dom is sent back to the client. And we're all just supposed to act like this isn't absolutely insane.
Isn’t that what Phoenix (Elixir) is? All server side, small js lib for partial loads, each individual website user gets their own thread on the backend with its own state and everything is tied together with websockets.
Basically you write only backend code, with all the tools available there, and a thin library makes sure to stich the user input to your backend functions and output to the front end code.
> And we're all just supposed to act like this isn't absolutely insane.
This is insane to you only if you didn't experience the emergence of this technique 20-25 years ago. Almost all server-side templates were already partials of some sort in almost all the server-side environments, so why not just send the filled in partial?
Business logic belongs on the server, not the client. Never the client. The instant you start having to make the client smart enough to think about business logic, you are doomed.
> Then they rediscovered PHP, Rails, Java EE/Spring, ASP.NET, and reboted SPAs into fullstack frameworks.
I can understand the dislike for Next but this is such a poor comparison. If any of those frameworks at any point did half the things React + Next-like frameworks accomplished and the apps/experiences we got since then, we wouldn't be having this discussion.
I still remember the joy of using the flagship rails application - basecamp.
Minimal JS, at least compared to now, mostly backend rendering, everything felt really fast and magical to use.
Now they accomplished this by imposing a lot of constraints on what you could do, but honestly it was solid UX at the time so it was fine.
Like the things you could do were just sane things to do in the first place, thus it felt quite ok as a dev.
React apps, _especially_ ones hosted on Next.js rarely feel as snappy, and that is with the benefit of 15 years of engineering and a few order of magnitude perf improvement to most of the tech pieces of the stack.
It’s just wild to me that we had faster web apps, with better organizarion, better dev ex, faster to build and easier to maintain.
The only “wins” I can see for a nextjs project is flexibility, animation (though this is also debatable), and maybe deployment cost, but again I’m comparing to deploying rails 15 years ago, things have improved there as well I’m sure.
I know react can accomplish _a ton_ more on the front end but few projects actually need that power.
> If any of those frameworks at any point did half the things React + Next-like frameworks accomplished and the apps/experiences we got since then, we wouldn't be having this discussion.
This is interesting because every Next/React project I see has a slower velocity than the median Rails/Django product 15 years ago. They’re just as busy, but pushing so much complexity around means any productivity savings is cancelled out by maintenance and how much harder state management and security are. Theoretically performance is the justification for this but the multi-second page load times are unconvincing.
From my perspective, it really supports the criticism about culture in our field: none of this is magic, we can measure things like page-weight, response times, or time to complete common tasks (either for developers or our users), but so much of it is driven by what’s in vogue now rather than data.
+1 to this. I seriously believe frontend was more productive in the 2010-2015 era than now, despite the flaws in legacy tech. Projects today have longer timelines, are more complex, slower, harder to deploy, and a maintenance nightmare.
We are having this discussion because at some point, the people behind React decided it should be profitable and made it become the drug gateway for NextJS/Vercel
I sometimes feel like I go on and on about this... but there is a difference between application and pages (even if blurry at times), and Next is a result of people doing pages adopting React that was designed for applications when they shouldn't have.
Correct, their main purpose is ecosystem lock-in. Because why return json when you can return html. Why even build a SPA when the old school model of server-side includes and PHP worked just fine? TS with koa and htmx if you must but server-side react components are kind of a waste of time. Give me one example where server side react components are the answer over a fetch and json or just fetching an html page?
The only example that has any traction in my view are web-shops, which claim that time-to-render and time-to-interactivity are critical for customer retention.
Surely there are not so many people building e-commerce sites that server components should have ever become so popular.
The thing is time to render and interactivity is much more reliant on the database queries and the internet connection of the user than anything else. Now instead of a spinner or a progress bar in the toolbar of the browser, now I got skeleton loaders and use half of GB for one tab.
It also decoupled fe and backend. You could use the same apis for say mobile, desktop and web. Teams didnt have to cross streams allowing for deeper expertise on each side.
Now they are shoving server rendering into react native…
It's really concerning that the biggest, most eye-grabbing part of this posting is the note with the following: "It’s common for critical CVEs to uncover follow‑up vulnerabilities."
Trying to justify the CVE before fully explaining the scope of the CVE, who is affected, or how to mitigate it -- yikes.
What’s concerning about it? The first thing I thought when I read the headline was “wow, another react CVE?” It’s not a justification, it’s an explanation to the most obvious immediate question.
It's definitely a defensive statement, proactively covering the situation as "normal". Normal it may be, but emphasizing that in the limited space of a tweet thread definitely indicates where their mind is on this, I'd think.
fwiw, the goal here wasn't to downplay the severity, but to explain the context to an audience who might not be familiar with CVEs and what's considered normal. I moved the note down so the more important information like severity, impacted versions, and upgrade instructions are first.
If there are so many React developers out there using server side components while not familiar with the concept of CVEs, we’re in very serious trouble.
We pioneered a lot of things with Opa, 15 years ago now. Opa featured automatic code "splitting" between client and server, introduced the JSX syntax although it wasn't called that way (Jordan at Facebook used Opa before creating React, but the discussions around the syntax happened at W3C notably with another Facebook employee, Tobie).
Since the Opa compiler was implemented in OCaml (we were looking more like Svelte than React as a pure lib), we performed a lot of statical analysis to prevent the wide range of attacks on frontend code (XSS, CSRF, etc.) and backend code. The Opa compiler became a huge beast in part because of that.
In retrospect, better separation of concerns and foregoing completely the idea of automatic code splitting (what React Server Components is) or even having a single app semantics is probably better for the near future. Our vision (way too early), was that we could design a simple language for the semantics and a perfect advanced compiler that would magically output both the client and the server from that specification. Maybe it's still doable with deterministic methods. Maybe LLMs will get to automatic code generation of all parts in one shot before.
Wouldn't make more sense keeping React smaller and left those features to frameworks? I liked it more when it was marketed as the View in MVC. Surely can still be used like that today but it still feels bloated
A framework designed to blur the line between code running on the client and code running on the server — forgot the distinction between code running on the client and code running on the server. I don't know what they expected.
(The same confusion comes up regularly whenever you touch Next.js apps.)
I do hope this means we can finally stop hearing about RSC. The idea is an interesting solution to problems that never should exist in the first place.
have you seen the code of next.js? its completely impenetrable, and the packages have legacy versions of the same files coexisting, it's like huge hairball
I've noticed a pattern in the security reports for a project I'm involved in. After a CVE is released, for the next month or so there will likely be additional reports targeting the same (or similar) areas of the framework. There is definitely a competitive spirit amongst security researchers as they try to get more CVEs credited to them (and potentially bounties).
I noticed requests that were exploiting the vulnerability were turning into timeouts pretty much immediately after rolling out the patch. I’m surprised it took so long for it to be announced.
Personally I prefer simple software without bugs! This security vulnerability highlights a serious issue with React. It’s a SPA framework, a server side framework, and a functional component library all at the same time. And it’s apparently getting so complex that it’s introducing source code exposures.
I’m not interested in flame wars per se, but I can tell you there are better alternatives, and that the closer you stay towards targeting the browser itself the better, because browser APIs are at least an order of magnitude more secure and performant than equivalent JS operations.
No, but it's primarily because Meta has their own server infrastructure already. RSCs are essentially the React team trying to generalize the data fetching patterns from Meta's infrastructure into React itself so they can be used more broadly.
I wrote an extensive post and did a conference talk earlier this year recapping the overall development history and intent of RSCs, as best as I understand it from a mostly-external perspective:
Like I said above and in the post: it was an attempt to generalize the data fetching patterns developed inside of Meta and make them available to all React devs.
If you watch the various talks and articles done by the React team for the last 8 years, the general themes are around trying to improve page loading and data fetching experience.
Former React team member Dan Abramov did a whole series of posts earlier this year with differently-focused explanations of how to grok RSCs: "customizable Backend for Frontend", "avoiding unnecessary roundtrips", etc:
Conceptually, the one-liner Dan came up with that I liked is "extending React's component model to the server". It's still parent components passing props to child components, "just" spread across multiple computers.
LOL. I must have divination powers.
I am currently working on a UI framework and opened an issue just 3 weeks ago that says:
***
Seems that server functions are all the rage.
We are unlikely to have them.
The main reason is that it ties the frontend and the backend together in undesirable ways.
It forces a js backend upon people (what if I want to use Go for instance).
The api is not client agnostic anymore.
How to specify middleware is not clear.
Requires a bundler, so destroys isomorphism (isomorphic code requires no difference between the client and the server/ environment agnostic).
Even if it requires a bundler because it separates client and server implementation files, it blurs the data scoping (especially worrying for sensitive data)
Do one thing and do it well: separate frontend and backend.
It might be something that is useful for people who only plan on having a javascript web frontend server separate from the API server that links to the backend service.
Besides, it is really not obvious to me how it becomes architecturally clearer. It would double the work in terms of security wrt authorization etc. This is at least not a generic pattern.
So I'd tend to go opposite to the trend and say no.
Who knows, we might revisit it if anything changes in the future.
***
And boy, look at the future 3 weeks later...
To be fair, the one good thing is that they are hardening their implementation thanks to these discoveries. But still seems to me that this is wholly unnecessary and possibly will never be safe enough.
Anyway, not to toot my own horn, I know for a fact these things are difficult. Just found the timing funny. :)
I remember some podcast interview with Miško Hevery talking about how Qwik was very emphatic about what code ran on the server and what ran on the client. Seems self-evident and prescient. It was a great interview as Miško Hevery is extremely articulate about the problems at hand. If I find it, I'll post.
Im confused, did the update from last week for the RCE bug also include fixes for these new CVEs or will I need to update again? npm audit says theres no issues
React patches one vulnerability and two more are revealed, just like a Hydra.
At this point you might as well deprecate RSC as it is clearly a contraption for someone trying to justify a promotion at Meta.
Maybe they are going to silently remove “Built RSC at Meta!” in their LinkedIn bios after this. So what other vulnerabilities are going to be revealed in React after this one?
> We are not using RSC at Meta yet, bc of limits of our packaging infra (it’s great at different things) and because Relay+GraphQL gives us many of the same benefits as RSCs. But we are fans and users of server driven UI and incrementally working toward RSC.
Oh boy, I somehow missed that React was offering these.
Google has a similar technology in-house, and it was a bit of a nightmare a few years back; the necessary steps to get it working correctly required some very delicate dancing.
The JavaScript fanatics will downvote me for saying this, but I'll say this, "using a single JavaScript codebase on your client-side and server-side is like cooking food in your toilet, sooner or later, contamination is guaranteed" [1]
This isn't a Javascript problem, this is a React problem. You could theoretically rewrite React and RSC in any language and the outcome would be the same. Say Python ran in the browser natively, and you reimplented React on browser and server in Python. Same problem, not Javascript.
> Say Python ran in the browser natively, and you reimplented React on browser and server in Python. Same problem, not Javascript.
Yes.
And since Python does not natively run in the browser, that mistake never happens.
With JavaScript, the desire to have "backend and frontend in a single codebase" requires active resistance.
It's the same vulnerabilities because Next uses the vulnerable parts of React.
Your rational is quite poor as I can write an isomorphic web app in C or Rust or Go and run parts in the browser, what then? Look, many of us also strongly dislike JavaScript but generally that distaste is based on its actual shortcomings and failures, you don't have to invent new ones plenty already exist.
> I can write an isomorphic web app in C or Rust or Go and run parts in the browser, what then?
If you have a single codebase for Go-based code running in an untrusted browser (the "toilet") and a trusted backend (the "kitchen"), then the same contamination is highly likely.
After Log4Shell, additional CVEs were reported as well.
It’s common for critical CVEs to uncover follow‑up vulnerabilities because researchers scrutinize adjacent code paths looking for variant exploit techniques to test whether the initial mitigation can be bypassed.
It turns out this introduces another problem too: in order to get that to work you need to implement some kind of DEEP serialization RPC mechanism - which is kind of opaque to the developer and, as we've recently seen, is a risky spot in terms of potential security vulnerabilities.
reply