A Tour of JavaScript & React Patterns

Client-Side & Static Rendering

Lydia Hallie

Lydia Hallie

Lydia Hallie
A Tour of JavaScript & React Patterns

Check out a free preview of the full A Tour of JavaScript & React Patterns course

The "Client-Side & Static Rendering" Lesson is part of the full, A Tour of JavaScript & React Patterns course featured in this preview video. Here's what you'd learn in this lesson:

Lydia shares the benefits and tradeoffs of client-side and static rendering. Client-side rendering only needs a single request from the server and allows content to be immediately interactive. Static rendering utilizes the server to pre-render the html which is more beneficial for SEO and cachability since the client is not waiting for any additional requests to the backend.


Transcript from the "Client-Side & Static Rendering" Lesson

>> So the first thing when you are working with React that you're definitely familiar with is client side rendering. So with client side rendering, essentially what happens is your user makes a request to your server, which responds with bare bones HTML. Browser parses this HTML, which contains nothing, then your client request and download the scripts, and then it will actually execute this which dynamically appends all those elements.

Only then will your user actually see stuff render to the screen. So all the rendering happens in the browser. So most basic implementation is, of course, having this route here, and then maybe a bundle.js and this bundle contains, I don't know, a DOM manipulation. But when you're working with React, if we go to any of, I mean, I won't go over it.

If we go to any of the other exercises, you will see that the initial load will just contain that ID root, just empty HTML. And as the bundle comes in, it automatically appends all those DOM nodes, and that's when a user is actually able to see things. So from a performance perspective, client side rendering returns in a pretty fast time to first byte.

Here's a time to first byte as the time it takes for the browser as a first byte of that initial response. But that is just the small HTML, nothing in it yet, it's just that ID root. So that's pretty good. However, when it does that, it still needs to fetch the bundle before the user is actually able to see anything and interact with anything.

So with client side rendering, what could happen if your bundle is pretty big, which is why bundle splitting is so important. Is that the first Contentful paint, the largest Contentful paints, and of course also the time to interactive. Because it also binds those events, handlers to all those components can be pretty long, or user can wait a long time.

However, client side rendering is definitely useful if your content should be interactive instantly. Because what it does is it parses the data, it renders it and also automatically binds those event listeners to them right away. Yeah, which is what sort of like the interactivity but then the bundle size is also not super SEO friendly.

Because when a crawler is crawling your website, it might take a while to actually fetch that bundle too long and it actually won't crawl it. So instead, what we might wanna use is static rendering. So with static rendering, what happens is, just gonna go up all the way, is that the HTML contents, the contents of a page are already pregenerated at build time.

So in that case, the client can request the HTML from the server, and it can instantly show something. Because the HTML, instead of just having that roots, it already contains all the elements that we eventually wanna show. Now, of course, this is just HTML, it's not interactive yet, and that's why the client, then, also still has to request a bundle.

But this bundle doesn't contain all those DOM append child methods, it just contains those hydration elements, so binding those event listeners to that static HTML. Cuz a bare minimum for a static rendered application is just to have listings, but when you're just using RAC normally out of the box, it will always default to client side rendering.

But maybe if you're using a framework like next.js, it's super easy to statically render. Let's see if this one is using. Yeah, so this example here is using next.js. I know a lot of frameworks also include static rendering, but this was just the easiest one to use. So here you can see that.

Let's see if we're actually using it. By default, it will actually off to static rendering just because it has so many performance benefits. So when we go into the network here, Inspect, I'm just going to reload this. You can see that it already contains all this HTML that we're eventually showing here, and it didn't have that, I'll try to find maybe the, These exercises here, then you might see the difference, cuz this is a client side rendered up that I could have used the listings as well.

But here what you see is when we initially load it, it contains nothing, it just has. Well, okay, you're also using Steglitz now so it's adding a bunch of other stuff. But the HTML itself on the initial quest is empty, whereas here it already contains the data that the browser needs to render.

Now, of course, it doesn't have the CSS yet because it's just HTML, it still needs to make that trip to fetch the CSS and then also fetch the bundle to hydrate them. But static rendering, let me see, it just comes with so many benefits because yeah, the time to first byte can still be very fast.

Cuz we just have the HTML file and in a lot of cases, because it's just static content, we can easily cache it on CDN. So the user doesn't always have to make that request to a server, we can just cache that static page near to our users or close to our users on the edge or any CDN close to the user.

But of course, what does happen is that we have to make an additional request to fetch the bundle. So even though the user sees content rendered to the screen, they think it's interactive, they don't think about that, where people don't think about, okay, I cannot click on this yet because the bundle hasn't fetched.

Well, maybe just developers think about that. Cuz it still needs to make the request to fetch the bundle and then attaches event handlers which is the hydration part. So, yeah, it can be very good depending on the page that you have. Yeah, so let's see where I was going with this.

But in a lot of cases, the stuff that we just saw was with not dynamic data, but you can still statically render also with dynamic data and there are a few approaches. So when you're using next, you can use something called get static props, and this method runs at build time.

So when we're building our application, so before we deploy it we build it, it will actually fetch this data and then inject that data into the HTML that eventually we parsed our servers and the CDN. So here I actually created a quick example showing this, and I know there are more frameworks that use an approach like this, it's just one way to render content.

So we have the getStaticProps, this one fetches these listings at build time, which then automatically passes these props to the app, which can statically render these listings. So from a user perspective, we end up with the exact same output, because the generated HTML is, again, the HTML that we saw before.

So it already contains the listing step will eventually render. Let's see. Yeah so the exact same, it's just different from a developer perspective, so the tradeoffs are the exact same. But imagine calling this method every time for a lot of pages. Cuz in next.js, you can just have those automatic pages here, if we have the page folder, it also includes route-based splitting by default.

But if you want to pregenerate a lot of pages, it might take a while. Maybe this fetch call takes three seconds to finish, if that'll run sequentially, our build may end up being like 45 minutes, if we want to pre-render lots of pages, maybe an e-commerce website or a blog, stuff like that.

And also in order, if we deployed this website and we wanted to update this data, we'd have to redeploy the entire website in order to update that data. So that's not great. Now, of course, one thing we can do here is to fetch the dynamic data client side.

So we render everything else statically, and then we just render the listings once the user can actually see something. So in the meantime, we'll just render a skeleton UI or something. So it fetches this data and only then will it show the listings. And of course, there's also the step with adding the event listeners and so on.

I won't really go too much into the implementation then, but example here, we're also using the SWRI like we saw before. So we can fetch API's or we can fetch the listings from the API and while it's loading, we'll just show a skeleton, and otherwise we'll just show the listings.

So in that case, we again, have a good time to first byte same with any statically rendered application. We also have a good first Contentful paint, because the first Contentful paint is essentially the view that we see, let's see here. This could be the first Contentful paint, but the largest Contentful paint doesn't happen until the listings are in the viewport.

So even though we have a good first Contentful paint in that case the largest contentful paints still has to wait for their listings to be fetched and then rendered.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now