My take on the current React and Server Components controversy
phryneas.de
phryneas.de
If you are struggling and want a no-bullshit stack, why not PHP or string interpolation in your favorite language? These approaches are easily more productive than anything that has come out over the last 5 years. All the excuses for why this won't work are almost certainly traceable back to ego/resume-driven development pressure rather than actual technical justifications.
Bookmarking MDN and literally treating it like the web bible is the solution for most of this. You don't need a JS framework. You don't need a CSS framework. Definitely not as of 2023. Between big wins like grid & flexbox, I can't think of anything I absolutely need to vendor out anymore.
Once you take the training wheels off and fall a few times, you will learn that this stuff isn't that scary. You can actually write javascript like "document.getElementById" and retain ownership over your soul. The next step is convincing your teammates of the same and then deciding upon some common patterns to follow that make it easier to collaborate. Put differently, let the frameworks evolve naturally over time. Don't force them in from the beginning.
Not in depth, but that's kind of my point. I don't really need to anymore.
But I'm so crazy fast in React + Tailwind that I really don't understand the frustration. Combined with Typescript, coding is just a joy for me these days.
Maybe I'm happy because I'm not jumping to each new framework trying to micro improve things, but honestly I'm not sure.
Coding the frontend in 2023 compared to 2013 feels like a piece of cake.
Facebook itself is a PHP app. React was invented to solve similar problems for Facebook.
If you're building a basic form app and you're able to make a business out of it in 2023, by all means, use some Jquery, a dead simple form UI and go to town. But if that app starts to evolve beyond a few screens or if more dynamic behavior is required, you owe it to yourself and your team to use a proper JS framework and toolset.
In 2023 JS is no longer necessary, for instance, Blazor also works fine, and works great for small teams building just LOB apps.
I find HTMX is a better alternative if I'm trying to write as little JS as possible, I find it smooths over the latency issue better and just lets me write normal web app code that feels like a SPA to use.
I have a webpage for my wife that has one form to submit they sends an email to her. I used plain JS. It took longer than I thought to implement because I had to reinvent the wheel, so to speak. I had to write everything from scratch.
For a business where the website is changing frequently with many developers, being able to leverage a plethora of existing code and solutions is very helpful.
Heck, even for people writing plain JS, I bet you find yourself writing helper functions and small libraries to DRY you code and make common things easier. Framework invented!
Found the guy responsible for the shitty local government websites leaking data left and right.
1. RESTful or API sites that just need a SPA to render
2. embedded boards that can never run node.js etc, there are millions or billions of them.
3. Eletron.js or React Native related applications, why do I need a next.js alike component involved at all?
Mixing SPA with SSR into React makes thing unnecessarily complicated, can SSR be an opt-in component just like what it used to be, so us SPA users do not need know your yet another revolutionary goodies that everybody must love it or he/she has no clue what's the best right now?I switched from Vue to React, now it seems I must switch back as Vue still separates SSR from CSR, god knows how long will that stay.
Hooks, and particularly useEffect, ruined it for me. I have given up trying to understand why changing button states or presenting modals has become so obtuse and frustrating. I don't care about updating my react-router and rewriting it again for the third or fourth or whatever time. I don't want another new testing library, another new "best practice", or another repeated mistake in the reinventing-the-wheel-cycle the React community seems obsessed with.
It's all so exhausting. I write Rails now with erb templates and some dumb javascript to toggle modals and change button colours. It's not cool but at least I can understand it six months later.
I did migrate my last project the barebones JS MVP -> React and regretted it immensely. It took about a month and didn't provide enough value to make it worth it.
It is literally a few pages and you can be ready to go with it. Especially that react didn’t drop backwards compatibility. I honestly don’t get all this negativity. There used to be a new framework in FE circles each month, but for several years now the churn has slowed to a halt.
Also, it literally just rerenders the state again if it changed. That’s it. There is hardly an easier model to exist.
The rest though, yeah, I dunno
Oh sure, there's new things to learn. But hooks encapsulate & contain the complexity much better than they used to.
I can only laugh to myself at the idea at class-based React or HoC was some halcyon "intuitive" React era. What we have now can be basically read top-to-bottom, with much less needing to deeply know lifecycle implications & complections & puzzle out implications each time we go to understand how a thing is behaving.
> On top of that, there was a mad rush throughout the ecosystem to implement them, many times poorly, leading to more confusion.
Can we use them poorly? Sure. Did we rush to play with the new tech? Absolutely! My though, it's sad to see this portrayed as a negative, as a strike against: this is how we learn! Open-source is strengthened by diversity, by learning in the wide. Initial adoption will be chaotic, but that vast experience leads more quickly to a healthier better normalized set of end behaviors!
The historical precedent for software framework development is having controlled, restrained ecosystem growth largely by a software giant or elite team, who is responsible for making perfect choices that everyone is going to have to live with either forever or until everyone's sick of all the old mistakes & makes a brand new library (like the long long long sequence of Microsoft frameworks for native & web). React by contrast as kept being successful because it keeps distilling out small core central ideas, and letting the ecosystem explore and innovate at the frontier with those ideas. Cathedral vs Bazaar models.
There's a lot of people whose idea of control and order is to believe in top-down systems, to believe in only guided careful controlled evolution. But this isn't the open source way, and, in my view, that way always leads to fragility and weaknesses. Including too many batteries in your solution leads to ossification & stagnation. Robust, long-term, good answers emerge only over time, only with lots of practice. And we're in such a beautiful age, where peership matters, where we have taste & sensibility to discern out of the many examples put before us what looks right & what looks good. These are the strengths of our era, our ability to iterate forward.
And with React Hooks, I think we're quite decently into the adoption curve. It's 4 years down the road from their introduction (16.8, in February 2019). I have a hard time imagining having to stick with the old ways. The old code that our small org refactors & cleans up is awful by comparison, is much less clear to read, has complex HoC concerns that rebuffed & scared most people. Meanwhile I think the ecosystem has really grown a very sophisticated smart sense of how hooks can & should be built, and is doing really stellar works with incredibly advanced hooks, that span front & back end both, which I doubt would have been a feasible wide-scale target previously.
Where we are is better. With great possibility & progress comes upheaval, yes, but it'd be a shame to dread it. Our designs are imperfect, our architectures ever apt for iterations; that we can adapt forward with grace & on so many frontiers - while still ending up speaking the same core language - all at once is truly a modern marvel. I can't imagine any better paths that what we've done.
I could say the same thing about Solid and its reactivity, and I have. But at least with Solid you know where the magic begins: an opening JSX tag. With hooks, it’s everwhere and you can’t know where magic and non-magic share a space because it’s externalized to linters which have limited capabilities to cross module boundaries.
I don’t like any of this magic but I’ll take “it happens predictably at an angle bracket with a well defined next character” any day.
Sure, solid is better in that respect, but react couldn’t have done any other way if it wants to work without a compile-phase.
And I have no idea why people (including React team members) keep saying React doesn’t have a compiler. That’s literally the only thing that makes it not plain JS.
Edit: and the compiler isn’t as specialized as Solid’s dom-expressions, but it’s definitely not just a DSL over an otherwise equivalent function call. There are special cases for specific props, and they have similar special case rules with Solid. And that special casing has only been more true over time, some people used to write React.createElement directly, but I think approximately no one writes the new jsx(…) directly because it’s specifically intended to be a compile target.
After telling him no, I became concerned that I was becoming all the lead developers I’ve worked with in the past that shut me down and, at the time, seemed to be holding back innovation on our team.
I get it now. I totally get it.
I gave up trying to be understanding and reason with them. It just seems new developers, and especially frontend developers see a shiny new package every week and want to try it. Before we put a stop to it we were lumped with a handful of projects that were frankly awful, with a bunch of spaghetti javascript code written in the flavor of the week which wouldn't compile on anything except a very specific version of a bunch of packages, whilst pulling in close to a gigabyte of random dependancies that nobody had any kind of handle on from a security point of view.
Basically you see how elegant or easy to do X in a new library but you don’t see how complicated it is to do Y. Y is complex in the new library and simple in your existing library
that doesn't sound like a big change.
Thankfully, the pages directory model is still just fine, so there’s no immense pressure for existing apps to migrate, and it can be done somewhat incrementally.
One point of confusion in the community has been around client components. If server components are new and exciting, does that mean client components are bad and we shouldn't use them anymore? No, it's okay to continue using them, but definitely want to acknowledge that can be draining for library maintainers to have to deliver that message. The client/server evolution of React is still in the early innings, so maybe this will be less of an education issue going forward. Client components = able to use the existing React ecosystem.
There's also some confusion about the React canary releases (https://react.dev/blog/2023/05/03/react-canaries). These features are ready for frameworks to adopt. The normal semver rules still apply for frameworks when they add experimental features (ideally behind flags). There is a separate experimental channel for React, that uses experimental features (like Server Actions). The infinite loop issue mentioned (marking a client component as `async`) now causes an ESLint error in Next.js.
Appreciate all of the suggestions in the post. A good conversation to have!
> Would you like to use App Router? (recommended)
It seems like users shouldn't yet be funnelled by default into using RSC.
This React Server Components seems to be a bunch of effort on throwing all that good will down the drain. It seems like they’re really excited about this new API and the react and nextjs teams have just charged forward with whatever this is, without really much consideration or anything else.
It is probably also easier for that “2nd or 3rd rate dev”, unless it is a legacy project where pre-hook react is mixed with it arbitrarily (and God save us, not even the “seniors” know what to make of that)
I think the React Team will soon be faced with an Angular 2.0 style situation where they are forced to break class components, hooks, etc to get people to use new patterns. The number of people who will do it out of goodwill has had to have been diminished to a minority percentage of React enthusiasts.
Personally, I just rock jQuery for my personal projects. I get the same dollar coming over the wire with a way faster time to live and reduced complexity.
What? Gotta link?
Have been using Lit.js in a hobby project and I'm really enjoying it. I'm not big on how stylesheets don't penetrate the shadow DOM but otherwise it just feels like I'm back writing heyday React.
I feel like the project should have reorganised into the React Client project and the React Server Side project.
With that disclaimed, I have a strong inclination to believe that RSC—its design and implementation, its apparent rollout strategy, communication and documentation around both—is going to lead to a probably underserved mass defection from React overall. I think so because the actual execution so far has substantially undermined the thing which made React so successful in the first place: perceived simplicity.
It’s not the first time this perception has taken a hit with a major transition. Hooks are a prominent example. But that hit and most others have turned out to be mostly temporary, or at least their fallout has been limited to people who reasonably don’t want to invest their time absorbing a fairly limited and transferable set of new concepts.
RSC simply isn’t, and cannot be, that. To understand RSC, you have to understand:
- Everything you already needed to understand to use React effectively
- Compiler directives that have to and might not ever transcend multiple build steps across multiple projects and teams
- Stuff is gonna request and respond with magic bespoke data on the wire for Reasons; the React team can explain the Reasons, but the state space is so large you’d have to be effectively a core contributor or early adopter to have any chance at holding it all in your head
- A supported feature matrix that’s essentially unknowable without keeping up as a personal hobby, because that matrix is partially determined by an external entity who can mark unstable features stable on their own whims and who are being actively encouraged to do so by the React team
- Not just the why is RSC but even the what is RSC in the face of incredibly casual and glib explanations like “yeah it is PHP actually” when it clearly is not, to anyone who has meaningful experience with both
- Any and all of what’s been understood so far is subject to become completely irrelevant at a moment’s notice, made so by an unknowable set of decision makers
- React is its own metaframework. You are explicitly expected not to use it directly, but rather to use some other metaframework’s implementation of an increasingly deeply complex set of interfaces—which you shouldn’t use directly
All of that, especially when combined, is in stark contrast with React’s defining features:
- View = (state) => abstract tree representing state, with some rules around…
- …effects are a messy reality but they’re comprehensible and composable if you invest some time understanding that
And, echoing the article author: I think there’s a probably a lot to like about RSC and the general technical strategy React is taking. But damned if it doesn’t feel like they’ve assembled an enormous boulder that will inevitably roll back down the hill they’re rolling it up while they also assemble the hill.
I made the same prediction about hooks, but the fundamental difference is that you can ignore hooks. You can drop in basically any state/effect system and interop with components using their own, or hooks, or whatever. But you literally can’t even import existing components or call existing APIs (even hooks!) without rethinking the call stack. Parents and children are much more coupled than they used to be. Some libraries will either earnestly adopt RSC, or will make minimal necessary changes to be compatible, and propagate the problem to each of their consumers. And they, in turn, will have to choose whether to adapt to these factors within React… or without.
And again, as an observer, it doesn’t seem like that prospect is being received very well. It seems like it’s being received the same way Angular 2 was: you’re in for some large dose of pain no matter what you choose to do, and “no one ever gets fired for choosing ___” feels a lot less of a safe bet.
And unlike the Angular 2 experience, the other options are increasingly viable and mature and well received. My knowledge transfer to Solid took a few hours playing with a toy project for fun. Which is notably far less time and effort than I’d expect to spend getting up to speed with React today.
I’d be happy to be wrong, I actually want the React team to succeed on several different highly principled vectors. But at minimum I think they’re going to need to really rethink how they’re communicating this set of changes and very probably how they’re rolling them out.