Building a website in 2021? I’m guessing you’re going to take a component-driven approach. It’s all the chatter these days. React and Vue are everywhere (is Angular still a thing?), while other emerging frameworks continue to attempt a push into the spotlight.
But components, in a more generic sense, have actually been around much longer. In fact, they go back to the early days of the web. They just haven’t typically been called components, though they still function as such. Server components are also reusable bits of code, but are compiled into HTML before the browser sees them. They are server-side components, and they are still very much a thing today.
Even in a world in which all it seems like we hear is “React, React, React,” both types of components are still relevant and can help us build super awesome websites. Let’s explore how client and server components differ from one another. That will give us a clearer picture of where we came from. And then we’ll have the information we need to dream about the future.
Perhaps the biggest difference between client-side and server-side components is what makes them what they are. That is the thing that is responsible for rendering them.
Server components are rendered by — you guessed it! — the server. They aren’t typically referred to as components. They’re often called partials, includes, snippets, or templates, depending on the framework in which they are used.
Server components can take two flavors. The first is the classic approach, which is to render components in real-time based on a request from the client. See here:
The second flavor is the Jamstack approach. In this case, the entire site is compiled during a build a process, and static HTML is already available when requested by the client. See here:
In both cases, the client (i.e. your browser) never sees the distinction between your components. It simply receives a bunch of HTML from the server.
Like server components, there are also two flavors of client components. The first is the more official web component, which makes use of the shadow DOM. The shadow DOM helps with encapsulating styles and other functionality (we’ll talk more about this later). Frameworks like Polymer and Stencil make use of the shadow DOM.
The more popular frameworks, like React and Vue, represent the second flavor of component, which handles DOM manipulation and scoping on their own.
Though this may feel unnecessarily tedious (especially if you’ve been around long enough to have been forced into this approach), there are benefits to it. It is a clear separation of concerns, where server-side code lives in one place, while the functionality lives in another. And it brings only the code it needs for the interactivity (theoretically), which can lessen the burden on the browser.
In a one-to-one comparison, server-side components tend to perform better. When the page that a browser receives contains everything it needs for presentation, it’s going to be able to deliver that presentation to the user much quicker.
That said, client-side components are often used within the context of a larger framework. React has Gatsby and Next, while Vue has Nuxt. These frameworks have mechanisms for creating a superior in-app experience. What I mean is that, while they may be slower to load the first page you visit on a site, they can then focus their energy on delivering subsequent views extremely fast — often faster than a server-side rendered site can deliver its content.
If you’re thinking, Yeah but what about pre-rendering and…
Yes, you’re right. We’ll get there. Also, no more spoilers, please. The rest of us are along for the ride.
Server components can be written in (almost) any server-side language. This enables you to write your templates in the same language as your application’s logic. For example, applications written with Ruby on Rails use ERB templating by default, which is a form of Ruby. Thus, Rails apps use the same language for the application itself as it does for its components.
However, there are frameworks like Tailwind CSS that are working to make this process less painful.
Many client-side component libraries come with CSS support (or at least a pattern for styling) right out of the box. That often means including the styles in the same file as the markup and logic, which can get messy. But typically, with a little effort, you can adjust that approach to your liking.
Welcome to the (hybrid) future
Neither type of component is the answer by itself. Server-side components require additional effort in styling and interactivity that feels unnecessary when we look at the offerings of client components. But then client components have a tendency to take away from performance on the front end. And because the success of a website often depends on user engagement, a lack of performance can hurt the end result and be enough not to want to use client components.
What does that mean for a future that demands both performance and a good developer experience? More than likely, a hybrid approach.
Components are going to have to be rendered on the server side. They just are. That‘s how we optimize performance, and good performance is going to continue to be an attribute of successful websites. But, now that we’ve seen the ease of front-end logic and interactivity using frameworks, again, like React and Vue, those frameworks are here to stay (at least for awhile).
So where are we going?
I think we’re going to see these components come together in three ways in the very near future.
Remember when you thought up that spoiler about pre-rendering? Well, let’s talk about it now.
These tools have gotten super popular because of this approach, and I suspect we’ll see them continue to advance.
2. Baked-in client-side pre-rendering
That’s a lot of compound words.
What I‘ve been thinking about a lot the last couple years is: Why doesn’t React (or Vue) take on server-side rendering? They do, it’s just not super easy to understand or implement without another framework to help.
On one hand, I understand the single-responsibility principle, and that these component frameworks are just ways to build client-side components. But it felt like a huge miss to delegate server-side rendering to bigger, more complex tools like Gatsby and Next (among others).
Well, React has started moving that way. Vue is already there. And Svelte has made this approach a priority from the beginning.
I think we‘re going to see a lot more development while these traditionally client-side-focused tools solve for server-side rendering. I suspect that also means we‘ll hear a little more from Svelte in the future, which seems like it’s ahead of the game in this regard.
That may also lead to the development of more competitors to bulkier tools like Gatsby and Next. For example, look at what Netlify is doing with their website. It‘s an Eleventy project that pulls in Vue components and renders them for use on the server. What it’s missing is the hydration and interactivity piece. I expect that to come together in the very near future.
3. Server-side component interactivity
Solving that problem seems to be the approach from the folks at Basecamp, who just released Hotwire, which is a means to bring some of the gains of client components to the server, using (almost) any server-side language.
Where do you think all this component business is going? Let’s talk about it.
Thank you for this write-up! When reading section 3. Server-side component interactivity, I immediately thought of Phoenix LiveView, and apparently there are active debates going on comparing it (and other frameworks) with Hotwire.
Y Combinator › news › item
How does Hotwire compare to Phoenix LiveView? | Hacker News
Y Combinator › news › item
This is the Ruby on Rails version of what Elixir Phoenix Live View and .NET Blaz… | Hacker …
I’d be interested where you see Meteor fitting with the above, I’m new to this but Meteor seems to answer client and server?
Great article. But why don’t you refer to Gridsome as a counterpart to Nuxt. It’s as good as Nuxt and unfortunately often underestimated from my point of view.
Looks like development of this tool is stopped these days (unfortunately, as my personal website is built on it and I love Gridsome)
Vue3 uses shadow DOM, now.
I don’t think React Server components really compare to Vue SSR. We can do SSR in React for years already, and server components are more related to Hotwire than Vue SSR in reality, and part of the “hybrid” trend (LiveView, LiveWire, Server-components, Hotwire…)