In light of the ongoing SPA Wars, frontend developers are closely following React’s answers to complaints about shipping too much JS and (relatedly) their interest in the rise of compilers, all of which factors into the involved back-and-forth dance I’m calling the server/client two-step.
Code executed on the client-side has the best interactivity, but server rendered sites are more performant. There are recognized costs and benefits to both approaches, but a growing number of creators and users of JS frameworks argue for a return to the server. The HTML-first philosophy, for instance, rejects client-rendered DOM generated by executing JS, and instead favors server-generated HTML. The increased adoption of “Component Islands,” usually shortened to just “Islands” (coined in 2019 by Katie Sylor-Miller, frontend architect at Etsy), is another popular response. In the islands pattern, parts of the page are completely static server generated HTML, while other parts are self-contained interactive apps. Astro, 11ty, and Fresh all use islands.
Which brings me to the React Server Component (RSC). A recent episode of JS Party concerning “The future of React” delves deeply into this thorny subject, and is therefore worth discussing for its relevance to the server/client two-step. In this conversation Dan Abramov, creator of Redux, and Joe Savona, part of Meta’s React team, outline their vision for the future of React—and, spoiler, it’s all about server components.
RSCs are a new feature in React 18, and considered “still experimental.” However, they have drummed up a significant amount of excitement. Huge names in the space including Vercel’s Next.js, Shopify’s Hydrogen, and Remix have all announced their involvement in polishing this feature in order to ensure its success. And this enthusiasm from the community appears merited owing to its grand promise. According to Next.JS’s documentation:
React Server Components allow developers to build applications that span the server and client, combining the rich interactivity of client-side apps with the improved performance of traditional server rendering.
React’s answer to the server/client two-step could be groundbreaking for the JS community. But what came across in the JS Party interview was the intractable complexity involved in balancing client with server in the frontend space. In host Jerod Santo’s words: “I’m sitting here thinking, all right, this sounds really complicated.” Why this difficulty in communicating RSCs? According to Savona:
It’s almost hard to talk about server components because depending on where you’re coming from I think different pieces might appeal to you.
Abramov echoes this sentiment:
With server components it is a little difficult to wrap your mind around if you are used to React because the way you add state, it forces you to create kind of a split point, so if you’re used to just creating components and putting state anywhere, built in within JS app router (that’s [NextJS’s] new version with server components) it does require you to learn how to compose components a little bit differently.
Despite difficulties in terms of cognitive load, explaining how RSCs work is of less importance than ensuring that it works. Recall that server-side rendering (SSR) has long provided the kind of background optimization that work-a-day frontend engineers want, but don’t necessarily need to understand in detail. And Abramov and Savona assure listeners that its server components do work. They explain that RSCs are currently in production in several projects including at Meta.
The complexity of RSCs is largely responsible for the bottlenecks and developer experience sacrifices Hydrogen noted last fall in their Roadmap, which resulted in their decision to abandon server components. Although Hydrogen continues to harbor high hopes for this technology:
We’ve found that keeping a clear separation around where your server is doing the work, and worrying less about how your server and client components might mix together, has resulted in a simpler developer experience that’s less prone to mistakes. We also heard from a number of developers that with most of their pages requiring some level of interactivity, the mental model of routes in a .server file, with interactive components in .client components became repetitive and error prone.
Although Andrew Clark, a React core contributor currently working on React and Next.js at Vercel, assures the community that there are no hard feelings, the dream of harnessing the advantages of client and server in a single, well-packaged solution remains elusive.
Happy for my friends at @remix_run and Shopify!
Even though Hydrogen is moving away from Server Components I deeply appreciate their work testing and iterating on the original proposal. Remix is great technology, and as RSC matures I hope it’ll find its way into the framework. https://t.co/MqhyAQQttn
— Andrew Clark (@acdlite) October 31, 2022
Interestingly, Zach Leatherman speculates that “miscommunicated expectations around React Server Components” may be at least partially responsible for the failure of Next.js v13 to ship with øJS, as Guillermo Rauch, CEO at Vercel, had promised in a 2021 tweet (“øJS is coming to Next”).
I’ll leave the technical aspects of the client/ server two-step to the lights of the JS community, and particularly framework developers who have studied this issue deeply and therefore have the best sense of how to harness the best of client and server. Although RSCs promise to combine client-side interactivity with server rendering’s recognized performance, it has a ways to go to pivot away from today’s clunky but functional two-step between client and server to a single, well-packaged solution that negates the need for a choreographed back-and-forth.
Disclosure: Vercel (Next.JS) is a RedMonk client.