How Server Components Change The Game Using Old Ideas

Introduction

Julian Burr kicks off the discussion about server components by drawing an analogy to the evolution of wind-powered cargo ships, highlighting the tendency to dismiss seemingly old ideas in software engineering. He emphasizes that his focus will be on the conceptual understanding of server components rather than delving into technical specifics, which will be covered in a later session.

The Early Days of Web Rendering

Julian harks back to the late '90s and early 2000s, an era of straightforward web development with plain HTML, CSS, and FTP deployments. Rendering involved a simple request-response cycle between the browser and server, resulting in fast user experiences but limited developer flexibility.

The Rise of Server-Side Languages

To address the limitations of static websites, server-side languages like PHP emerged, enabling dynamic content and improved developer experience. However, this came at the cost of increased server workload and slower response times, particularly noticeable during user navigation.

JavaScript and AJAX to the Rescue

JavaScript and AJAX were introduced as solutions to enhance the user experience by enabling asynchronous updates. While this fixed the perceived performance issues, it led to fragmented codebases and, without proper frameworks, often resulted in the infamous "spaghetti code" dilemma.

The Era of Client-Side Rendering

The advent of client-side rendering and single-page applications (SPAs) with frameworks like Angular, React, and Vue shifted the rendering burden to the client. This improved developer experience and provided smooth navigation, but the initial render became a bottleneck, impacting UX, accessibility, and SEO.

Balancing UX and DX: Static Site Generation and Server-Side Rendering

To counter the drawbacks of client-side rendering, developers revisited older concepts. Static site generation (SSG) emerged as a solution for static content, generating HTML at build time, while server-side rendering (SSR) addressed dynamic content needs by generating HTML on each request, both followed by a "hydration" step to add interactivity.

Introducing Server Components

Server components, introduced in React in 2020, are presented as an enhancement to SSR and SSG, aiming to alleviate the hydration bottleneck by rethinking how we approach interactivity and static content in component-based frameworks.

The Root of the Hydration Problem

Julian argues that the hydration issue stems from the shift in mindset when client-side rendering gained traction. The assumption that everything could be interactive by default in frameworks like React led to inefficient rendering processes when applied to server-side scenarios.

How Server Components Aim to Solve It

Server components offer a way to explicitly define components as either static or interactive, allowing bundlers to optimize code splitting and hydration. This results in smaller client bundles and faster, more targeted hydration, referred to as "partial hydration."

Beyond React: Exploring Other Approaches

Julian highlights frameworks like Astro and Quik, which tackle the hydration challenge with different approaches. Astro focuses on a "static by default" mindset, while Quik strives for "zero hydration" by employing code splitting and resumable state mechanisms.

Conclusion: The Future of Web Rendering

While acknowledging that React's server component implementation is still evolving, Julian expresses optimism about the concept's potential to improve developer experience, best practices, and overall website performance. He encourages developers to stay informed about server components and related frameworks, as they are poised to shape the future of web development.

I have a meme that's stuck in my head and it's been living rent free for a while there.

It's basically a, an article that's about how wind powered cargo ships About to revolutionize the shipping industry and in good old internet fashion, social media took on that article and wrapped it to pieces with comments like, wind power ships, what a time to be alive.

And just generally mocking the idea that something like wind power ships, which in their mind was just reinventing sailboats, which we had for thousands of years, how that could be deemed like an innovation or revolutionary in any shape or form.

And I think about it a lot because.

It's how I sometimes feel about software engineering and the front end communities and ecosystems where we often see new ideas and we put them aside or even more, or even worse, like laugh at them.

Because we think they're just old ideas dressed up in some form.

Today, I'm going to talk about server components, but I'm not going to talk about the deep technical details of them, or I'm going to show any code examples.

Richard, who's talking after me, will do a much better job at that, so stick around for that if you're interested.

What I want to do instead is really focus on what server components are conceptually.

And why we need them.

And I think for that, we need to take a brief look at the history of web rendering, the different strategies that we've used in the past, the problems that they were trying to solve, and how server components fit into all of that.

One disclaimer before I get started.

It's more of a content warning.

There might be some nostalgia popping up here and there throughout the talk.

I'll try to keep it to a minimum, but for younger people here, please stay with me when I drift off and start dreaming about jQuery and the good old days.

I'll promise I'll bring it back on track, but it's, hard.

All right, let's get started.

And what better place to start than the very beginning?

Late nineties, early two thousands, we're talking plain HTML, plain CSS for the most parts.

Those were simpler times.

Simpler times how we wrote code, it was basically just write your files, then you would drag and drop your files straight onto the server, using your favorite FTP client, and you would call that a production deployment.

And rendering websites was also a lot simpler.

And I know I'm going to oversimplify a little bit here and throughout the talk because I only have 30 minutes and I want to focus on like the key bits that actually help me make my point.

But in a very rough form, rendering a website at that time meant the browser would make a request to the server.

The server would look up files that are relevant for that request.

Then the server returns those files and the browser would render a page based on them.

And from a user experience perspective, this is awesome, this is great because it's super quick.

There's not actually much happening.

The server only needs to do a file lookup and even on the browser there's not much happening, it just renders the page, there's not much forth and back, there's not any extra logic going on.

But it has some obvious drawbacks, from a developer experience perspective.

So if you had, large applications, large websites, you needed to write a lot of code.

Especially, a lot of redundant code, because there's no real form of abstraction that helps you with reusable functionality, reusable layouts or components.

And if you wanted to write dynamic applications, it's even worse because you can't really source content from external data sources like databases, or serve content to users specific to the user who requested it.

So we started using server side languages, like PHP.

So these are the WordPress kind of days, so we're still in the early 2000s.

But what that basically meant is now when the browser makes a request, the server actually does stuff.

Actually, there's logic happening, it can go to a database and actually fetch, external data, and then it generates the HTML on the server, trans back to the browser, doesn't, for the browser it looks the same.

It just renders the page with the HTML that it got.

And that fixes all of our DX issues, right?

Because now we can build dynamic applications, we can build larger applications, we can, because now we can have templates, we can have components that are abstracted out, reusable logic and all that.

But it introduces a UX problem.

Because now that the server actually does stuff, the response time will be a lot slower.

That becomes very apparent when the user starts navigating, because then the page goes blank.

Because that's what browsers do, while it's waiting for the server response.

And the longer the server takes to do stuff, the more complex the application gets, the more that actually becomes an issue for users.

So how do we deal with that?

Let's introduce JavaScript, the main protagonist in this room today.

And its small sidekick, AJAX.

So AJAX stands for Asynchronous JavaScript and XML.

And it was invented by Google to essentially allow websites to request stuff from the server after the page has already been rendered.

And what that allows us to do is, this initial render will still look exactly the same, but now when the user navigates we intercept, and we don't let the user, the browser do its default thing, and instead we're in full control.

So we're in full control over what we show while we're waiting for a response, so we can show nice loading states.

We're in full control over what we're requesting from the server.

Now we can say, okay, I already have the layout, I already have most of what I need, just give me the content, just give me what changes.

So we reduce the amount of work the server needs to do.

We've reduced the amount of data that the server needs to send back over the network.

And we're also in full control over what we then do with the data.

So we don't have to replace the whole website.

We can just replace selectively the parts in our website that change.

And this is great.

Like the user experience problem is fixed.

Now when a user uses our app and navigates through, it's a smooth experience.

The perceived performance is even better because now The user gets visual feedback, but it's again a step back from a developer experience perspective.

And I hope you start seeing a pattern here, like the whole evolution of web rendering is essentially just a constant game of tug and pull of us figuring out what is the right balance between UX and DX trade offs.

And in this case, the DX trade offs are, for one, the code base is still split in two parts.

One is the server side code, the PHP, that generates your HTML, and one is the JavaScript on the browser, which is not ideal to start with, but now it gets really messy because the server generates HTML, sometimes only subparts, sometimes only data, the client suddenly now starts mutating HTML and removing elements, adding elements.

So not having those in the same code base is, not ideal.

And the other problem.

Was at the time, I think AJAX was just a little bit ahead of its time.

I think that the support of frameworks was very little.

They were very rare that you had, bigger MVC frameworks that helped you build complex applications.

Which meant a lot of the time we would just go away, and I'm as guilty of that as anyone else, and write our own solutions, to mostly common problems.

Which led to what we, today, we always think of is, when you think of jQuery, when you think of AJAX, you think of spaghetti code because that's what we wrote.

So how do we fix that?

What if we moved more stuff to the client?

What if we moved everything to the client?

So this will start looking more familiar now.

It's basically the era of client side rendering, single page applications, and all those frameworks that you know, starting with KnockoutJS, Angular, and then eventually moving into React and Vue.

And what it meant was, what if we, when the browser request comes in, we go back to just serving static files.

And the HTML file that we serve is just an empty shell, it's just div div.

But now we're also serving like a JavaScript file, and that JavaScript file defines everything that goes into that shell.

And that means for the initial render, that's just an empty div.

That's fast, but that's not really useful for the user.

And then the browser parses that JavaScript data and goes back.

And throughout it will very likely need to go back to the server or it stumbled across some assets, some more JavaScript, some images then those get returned, then those need to get parsed.

Or now it stumbled across like a request for some data from our REST API, so it has to go back to the server, actually has to start doing stuff.

And you hopefully can see that this initial render is awful.

It's, very, it can easily get very long, especially the more complex the application gets, so it doesn't really scale well.

But once that is done, we're back in a good user experience because we're back to where AJAX worked well.

Of now we're in full control.

When the user navigates, we only request what we need.

Stuff comes back, we only replace what we need.

The developer experience increased heaps because now we have all those great frameworks.

I'm going to stick to React because that's the stage here.

But all of those great frameworks that help us abstract out all of the difficult parts of building complex applications.

But the user experience, especially of that initial load suffered.

And, not only for the user itself, but also for, side effects of just serving an empty div is not great for accessibility, search engine optimization and all of that stuff.

So how do we deal with that?

This is where we start seeing people taking some steps back, looking at old ideas and trying to apply the good parts of them to all of the modern technology that we have.

And one of the solutions is static site generation.

So the idea for more static websites like marketing websites, blogs, etc.

Where the content doesn't change too much.

What if we went back to square one and, or the other way around.

What if we still use all of those great frameworks.

What if we still use React to write that website.

But then, before anything else happens, either locally or in CI CD through a pipeline, what if we generated static HTML from that?

And what if we then just take those generated files, put them on the server, and the server is back to square one?

For the server, it just means, okay, when a request comes in, now I just need to look up files again.

That's quick.

And I return the files, and then the browser can just render that.

But now we have a new step.

And it's because we wrote the website in JavaScript, means very likely there's a lot of interactivity in there.

There's some local state, there's some event listeners like we've just seen, there's some effects as we've just seen.

All of those don't exist when you, render a static HTML website.

So yes, the page is immediately rendered, but it's not interactive yet.

The user can't interact with it.

So we have a new step that's called hydration, where we run the JavaScript again to be able to get all those dynamic parts and inject them into the website.

Once that's done, cool, website is interactive and the rest is the same as for our single page application.

So we fix the initial render with that caveat of dehydration.

And we kept all of the other good parts of the user experience.

That obviously only works for static content.

So similar to the plain HTML, that doesn't work very well for dynamic content.

So for dynamic content, we went to server side rendering.

And this is where frameworks like Next.

Js, Remix, FreshJS, whatever, became really popular.

And it's doing the same thing, just on demand again.

So we're back in the PHP days, where when a request comes in, the server does stuff to generate the HTML.

Now it's just NodeJS instead of PHP, which is JavaScript, which means, again, back to the idea, we can use our existing frameworks, we use React to write the website, because we can just run it on the server, generate the HTML, and return that HTML.

And then similar to static site generation, we can immediately render the page, but we have to have that hydration step, because all of the interactivity is gone when it's rendered on the server.

The rest is the same as all the others.

Here we get to server components.

Server components have been introduced, or React server components have been introduced, in 2020.

And have been pretty much experimental, since then.

And we've seen them start to be scattered around and introduced into the wider ecosystem.

Most famously through, into, NextJS, where it's the core of the new app router.

And It's important to, to, note that server components are not an alternative strategy to rendering.

It's not an alternative to server side rendering.

It's more, or it's better to think of it as an enhancement.

It enhances server side rendering, static site generation, and those kinds of strategies.

And what server components try to solve for is that hydration bottleneck that we've just seen.

But where does that hydration problem come from?

We didn't have that when we were just rendering through PHP and AJAX, right?

So what is causing the problem in the first place?

And fundamentally, and I'm again simplifying things here, but fundamentally I think the problem It all started when we went to client side rendering, and when we started having those frameworks that were built to let you build websites in JavaScript that's run, that's supposed to run in the browser.

And that worked fine while we were doing the client side rendering, but then when we started to move stuff back to the server, but kept those frameworks, the concepts didn't work that well anymore.

And, basically what's happening in a very simplified form is because static HTML can't represent any interactive parts, any dynamic parts, there's no way we would have, or you would describe in static HTML wouldn't affect this.

So whatever we do on the server needs to generate static HTML, needs to return that.

Once that is rendered, we have to rerun that whole JavaScript.

To create a virtual copy of that page to then inject all of the interactive parts.

And when you think about it, that's the exact opposite of what we were doing back in the PHP and AJAX days, where we would write HTML, or generate the HTML through PHP.

We wouldn't even think about creating effects in PHP.

So we would just write static HTML that would get returned to the server, and then we would write separate JavaScript.

Let's say with jQuery, where we would very specifically target elements on the page to make them interactive.

So the mindset completely shifted from in PHP days, static by default, then we render and then we specifically add interactivity, to the React days where everything can be interactive by default, everything can be stateful and whatnot.

And then we render it, and then there's a, okay, what now?

For the bundler, there's no way to know which part of your code is interactive or static.

So what the bundler, or like what we do at the moment, is really just rerunning the whole JavaScript on the client, after we've already run it on the server to generate the HTML.

How server components are planning to fix that is to take that step back again, and say okay, what if we gave, developers, the ability to say, cool, which components are static and which components are interactive.

Which components are essentially server components or which components are client components.

And what if, like in the PHP days, we say everything is just static by default.

But we give the user the ability to opt out of that and define something as client component.

Once the bundler knows that, that's huge, right?

Because that means everything that's defined as a static component can just be excluded from the client bundle.

So whatever we send as JavaScript to the browser in the end, it can completely be excluded.

So for big dependencies like, if you're formatting markdown to HTML, or if you have code snippets on your website and you want a syntax highlight, all of that stuff used to cause like massive bundle sizes on the front end.

Now we can just say, OK, just render that.

Once it's rendered, we don't need anything.

Of that anymore.

So exclude that from the, client bundle.

And what that also means is we can be much, more specific about what needs to be hydrated.

So that hydration step doesn't need to be, just create a virtual copy of everything anymore.

It can be, oh, just create virtual copies of these individual client components and switch those up, and the rest can stay the same.

So it's much more efficient.

And that's basically what happens when we look at a simplified rendering cycle of a website with several components.

It looks the same, but actually the work that is done in the JavaScript bundle that's now shipped is a lot smaller.

It gets rendered, the hydration step is still there, but it can be way more targeted and way faster.

And that's essentially why we call it partial hydration, because we still do hydration, but it's just parts of the page.

And React is not the first framework or first library to look at that, and it's not even the front runner.

There's a lot of other libraries that play with the same idea.

Think about, like, how do we take that step back?

And allow the mindset to shift back again to the PHP days.

And one framework that you might have known or might have already played with is Astro.

And again, it does exactly the same thing of like, how can we turn the developer experience back to just, you're writing static websites by default.

Ideally, that doesn't need to ship any JavaScript for runtime, but then allow the developer to easily opt in where they need that JavaScript runtime.

And then there's some frameworks that take it even a step further, and call it zero hydration.

So the most popular of that is probably Quik.

It's made by the creator of Angular.

And it's doing exactly that.

It says, okay, we don't want to run hydration at all.

And the ways to achieve that, there's many things that it does.

But for one, they serve partial, state like stuff through the HTML.

They just, serialize it, send it through.

So whatever the server sends, the client can resume.

So resumable state is a huge keyword there.

But for us, for the, for this context, the more important bit, is they're very heavy on the code splitting.

So every function, every closure, gets split into their own very little bundles.

And then instead of hydrating the page when it's rendered, we actually wait for the user to interact with the elements that need to be interactive, and we then load the chunks on demand.

And, obviously, there's a balance, in these approaches, and we're still trying to find that.

But in general, this is a really smart approach, because that scales essentially infinitely, because your user will never interact with all of the elements on your page, so for full hydration, or even partial hydration, we're still wasting a lot of that time hydrating elements that will never be interacted with.

The conclusion.

Do I think server components are the future?

Conceptually, yes, 100%.

I think the concept of server components very specifically tries to fix a problem where we broke conceptually, the mindset that we have, how to render websites when we introduced client side rendering.

And it's trying to bring back the mindset of, cool, if you define everything as static and then inject interactivity, that also fixes a lot of the anti patterns, and problems that we've started introducing when frameworks like React became more and more popular.

So like we've just heard, useEffect has very specific use cases that are just, going, okay, if you can't do it properly, these are escape hooks, essentially.

Let's be honest, we started using hooks, especially like useEffects and useState and all that stuff way too much.

We started using them out of convenience because they work, and we don't immediately see the downsides of them.

And server components help us understand for a lot of that stuff, you don't need them.

If you, think about your component as this is only ever going to get rendered once and that's on the server, do you really need all of that stuff that's in there?

And if you do, can you build that into smaller chunks within that component?

With that, I also think it helps us understand how to use the platform better.

And I know that's starting to become a meme where especially Remix is pushing hard on that of people need to understand the platform, use the platform better, that makes your code better.

I think it's true though.

And.

In this case, for example, I keep saying like server components can't have state, which is true if you think about state as like a useState local memory kind of state.

But what they can do is use the platform.

And what do we use to use the platform for state on the server is the URL.

So think about If I need that state in my server component, can I actually use it as a URL query parameter, have it serialized, which leads to a better user experience because everything is in the URL state, users can share that state, users can refresh the page without losing it.

So long story short, I think server components conceptually, will lead to a lot of better patterns, better best practices, and just clean up over our mindset.

Do I think React server components are perfect, and especially the way they're implemented in NextJS?

Absolutely not.

And I think that's fine.

There's a reason why they had this experimental period.

Where they, it's basically us trying out, figuring out, what is the best developer experience for this?

How can we help developers understand what these are doing?

And I think NextJS did a good job in introducing it.

I just don't think we're quite there yet.

And I definitely see server components and the way we use them evolve over the next years, to hopefully an easier application for developers.

And what makes me confident with that is looking at all these frameworks that I just mentioned, like Astro and Quik and all of the other players that just look at the same problem from different angles, have different ideas for solutions.

And all of that will drive the evolution of the next step of web rendering.

Cool.

Last, question.

Do I thank everyone?

Everyone in this room should start using Server Components.

I only mention this because I hate when talks go Oh cool, I show you Server Components, they're the silver bullet for everything, and if you don't use them, you're stupid.

Because I think those talks are like it's bad advice and it's useless advice.

I don't know your context.

I don't know your background.

I don't know the requirements that you have in your projects.

You might only work on smaller applications, smaller websites, where you don't even notice that hydration bottleneck.

This is the first time you hear about it.

And you don't really care about the bundle size.

Then the win that you get from server components is likely very small.

It's still a win though.

So instead of telling you have to use them, what I hope is over time server components will just get baked into the frameworks that we use, the patterns that we, use, the best practices that we teach so that people don't even have to care about it anymore.

Whether or not it's a good idea, it's just part of how we do things.

And yeah, so that, that is my suggestion.

If you take anything away from this, it's keep an eye on server components, even if you don't use them.

Keep an eye on the frameworks, even if you don't plan to use them, because I think it will become part of how we build websites in the future.

Thank you.

HOW SERVER COMPONENTS CHANGE THE GAME USING OLD IDEAS

Julian Burr

Engineering Lead
Vouch
Throughout the presentation Julian illustrates some concepts with simple animation. These aren't typically described in text as they illustrate Julian's description.

@DAILYTECHNOLOGYNEWS

@GUABIRUDROPOUT2

WIND POWERED SHIPS!? WHAT A TIME TO BE ALIVE!

@DACO-BROMANIAN

WE REALLY ARE IN THE FUTURE

This wind powered cargo ship is set to change the way we ship the goods across oceans. The model is very practical and is looking at a possible launch in 2024. https://ift.tt/2mKa9PB

Image of a large cargo ship named OCEANBIRD with five tall, modern sails on an ocean, accompanied by text bubbles with social media comments. Sarcastic tweets appear over the image in succession.

GOOD OL’

HTML

Illustration of a desktop computer displaying the text "GOOD OL' HTML" on the screen. To the left of the computer are stacked books and a teacup. A green potted plant is on the right side of the computer.

Being Dynamic on the Server

SERVER GENERATES PAGE HTML

Illustration of a computer screen displaying a server generating HTML. The server is depicted with SQL and database symbols, along with a progress indicator. The background includes books, a teacup, and a plant.

INTRODUCING JS AND AJAX

An illustration featuring a desk with computer, a mug, books, and a plant.

RENDER PAGE

Illustration of a computer screen displaying a webpage being rendered, with books, a mug, and a plant in the surrounding environment.

MOVING TO THE CLIENT

REQUEST PAGE

STATIC SITE GENERATION

SERVER SIDE RENDERING

SERVER COMPONENTS

PARTIAL HYDRATION

ZERO HYDRATION

Conclusion