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.
Some libs in the stack are great but they were made pre rsc fad.
Also, you're just wrong? You literally cannot serve RSC components _at all_ even in TanStack Start yet. Even when support for them is added it will be opt-in for only certain kinds of RPC functions and they will work slightly differently than they do in Next.js app router(where they are the default everywhere). RPC != RSC.
Plus you can always stick to using TanStack Router exclusively (zero server at all) and you never will even have to worry about anything to do with RSCs...
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.
Not to mention the whole middleware and being able to access the incoming request wherever you like.
You still need API routes for stuff like data-heavy async dropdowns, or anything else that's hard to express as a pure URL -> HTML, but it cuts down the number of routes you need by 90% or more.
Personally I don’t like it but I do understand the appeal.
But I really, really do not like React Server Components as they work today. I think it's probably better to strip them out in favor of just a route.ts file in the directory, rather than the actions files with "use server" and all the associated complexity.
Technically, you can build apps like that using App Router by just not having "use server" anywhere! But it's an annoying, sometimes quite dangerous footgun to have all the associated baggage there waiting for an exploit... The underlying code is there even if you aren't using it.
I think my ideal setup would be:
1. route.ts for RESTful routes
2. actions/SOME_FORM_NAME.ts for built-in form parsing + handling. Those files can only expose a POST, and are basically a named route file that has form data parsing. There's no auto-RPC, it's just an HTTP handler that accepts form data at the named path.
3. no other built-in magic.
RSCs are React components that call server side code. https://react.dev/reference/rsc/server-components
Actions/"use server" functions are part of RSC: https://react.dev/reference/rsc/server-functions They're the RPC system used by client components to call server functions.
And they're what everyone here is talking about: the vulnerabilities were all in the action/use server codepaths. I suppose the clearest thing I could have said is that I like App Router + route files, but I dislike the magic RPC system: IMO React should simplify to JSON+HTTP and forms+HTTP, rather than a novel RPC system that doesn't interoperate with anything else and is much more difficult to secure.
Vercel has become a merchant of complexity, as DHH likes to say.
I don't care about having things simple to get started the first time, because soon I will have to start things a second or third time. If I have a little bit more complexity to get things started because routing is handled by code and not filesystem placement then I will pretty quickly develop templates to handle this, and in the end it will be easier to get things started the nth time than it is with the simple version.
Do I like the app router? No, Vercel does a crap job on at least two things - routing and building (server codes etc. can be considered as a subset of the routing problem), but saying I dislike app router is praising page router with too faint a damnation.
Align early on wrt values of a framework and take a closer look at the funder's incentives.
An example of this is filesystem routing. Started off great, but now most Next projects look like the blast radius of a shell script gone terribly wrong.
There's also a(n in)famous GitHub response from one of the maintainers backwards-rationalising tech debt and accidental complexity as necessary. They're clearly smart, but the feeling I got from reading that comment was that they developed Stockholm syndrome towards their own codebase.
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.
So I ran a static analysis (grep) on the apk generated and
points light at face dramatically
the credentials were inside the frontend!
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’ve been out of full stack dev for ~5 years now, and this statement is breaking my brain
These kind of node + Mobile apps typically use an embedded browser like electron or a builtin browser, it's not much different than a web app.
You have two poison pills (`import "server-only"` and `import "client-only"`) that cause a build error when transitively imported from the wrong environment. This lets you, for example, constrain that a database layer or an env file can never make it into the client bundle (or that some logic that requires client state can never be accidentally used from the stateless request/response cycle). You also have two directives that explicitly expose entry points between the two worlds.
The vulnerabilities in question aren't about wrong code/data getting pulled into a wrong environment. They're about weaknesses in the (de)serialization protocol which relied on dynamic nature of JavaScript (shared prototypes being writable, function having a string constructor, etc) to trick the server into executing code or looping. These are bad, yes, but they're not due to the client/server split being implicit. They're in the space of (de)serialization.
Sure, but even though it's "build time" it feels more like runtime (indeed I think the only reason it works that way is your code is being run at build time). I should be able to look at a given piece of code and know locally whether it's client-side, server-side, or polymorphic, rather than having to trace through all its transitive imports.
Have a Landing/marketing page? Then, yes, by all means render on the server (or better yet statically render to html files) so you squeeze every last millisecond you can out of that FCP. Also easy to see the appeal for ecommerce or social media sites like facebook, medium, and so on. Though these are also use cases that probably benefit the least from React to begin with.
But for the "app" part of most online platforms, it's like, who cares? The time to load the JS bundle is a one time cost. If loading your SaaS dashboard after first login takes 2 seconds versus 3 seconds, who cares? The amount of complexity added by SSR and RSC is immense, I think the payout would have to be much more than it is.
they may get other vulnemerelities as they are also in JS, but RSC class vulelnebereleties won't be there
I can't recommend it enough. If you never tried/learnt about it, check it out. Unless you're building an offline first app, it's 100% the safest way to go in my opinion for 99.9% of projects.
Instead of creating routes and using fetch() you just pass the data directly to the client side react jsx template, inertia automatically injects the needed data as json into the client page.
React team reinvent the wheel again and again and now we back to laravel
In retrospect I should have given it more thought since React Server Components are punted in many places!
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.