Transcript from the "Incremental Rerendering & SSR" Lesson
>> Another thing you could do, now for cell with Next.js, we call it incremental static regeneration. But there are frameworks that have other approaches with kind of a stale while revalidate approach. And this is also to kind of add this dynamic data. So we can opt into only pre-render, a subset of all the pages, and render everything else on demand.
[00:00:19] So let's say we know we have 1,000 listings. We only want to make sure that we pre-render the latest 20 listings that are maybe visible instantly to the user and that the user is likely to click. But everything else will be generated on demand. So in that case, the statically generated page, when a user requests a page that hasn't been generated yet, can still be cached by a CDN because it's static.
[00:00:44] So it's really only the first user that request those pages that haven't been generated yet that might experience worst performance. But everyone else can still experience from this cache or benefit from this cache response. And then also we have the stale while revalidate. So we can automatically invalidate the cache of this static page after a certain time.
[00:01:05] So if a user requests a stale page, so it has been cached for longer than we showed, it will automatically regenerate that in the background and replace the cache. So a user will initially see the stale content, but the next time they request it, they automatically see this new data.
[00:01:19] Because the getStaticProps method again run in the background, in Next.js's case, in a serverless function, but it could also be in your server. So this is a great way to have this dynamic data maybe based on a certain interval and to make sure that your users are still able to see something because there's always a cached response.
[00:01:38] I won't really go too much into the implementation of this one just because this is so Next.js specific. And it's more about the possibilities with static rendering and how you could possibly add dynamic data. Now, the other very popular pattern is server-side rendering. So with server-side rendering, we generate the HTML, so all the HTML on the server or serverless function on every request.
[00:02:03] So the user request the page, we just generate it and we show it to them right away. And then, of course, we have to create or make an additional request to fetch the bundle to hydrate those static HTML elements. And this is a great way if the page that you're rendering is highly dynamic or just contains any data that is within that request.
[00:02:24] Maybe a user cookie, I don't know, maybe missing authentication states. But in general, you probably wanna avoid server-side rendering cuz, as you can see, the page still had to be generated or the user requests it. And this could take a while. So it's still great for those dynamic pages, but for just a normal standalone application, you might not need it.
[00:02:48] So in React, we can actually implement server-side rendering with, for example, a renderToString, and then the hydrateRoot on the client. So it gets that, it makes the DOM tree, and it then hydrates it. Hydrating, you're adding those event listeners. Again, yeah, so next, we can use server-side rendering with instead of using getStaticProps, we can just use getServerSideProps.
[00:03:09] And this will automatically server render this page. So for example here, If I, Go in here. Now, from a user perspective, this won't be that much different compared to static rendering because the return HTML is the exact same as we saw before. However, this HTML is generated on demand on the server instead of pre-generated at build time, maybe on your own device, on some built server.
[00:03:43] Now, the performance for server-side rendering and static rendering look pretty similar. But the biggest difference here is the time to first byte. Because it can take a while from when a user requests it to when the server can actually respond with the data that it still has to generate.
[00:03:56] So when the time to first byte is slow, the user just looks at a blank page, which is not great. You probably wanna avoid that. But it's still great for having those very personalized pages or any page that's render blocking, really. Cuz we can just say, you don't have the right cookie, you don't have the right authentication state.
[00:04:13] I don't want to render this page. And another downside to server-side rendering is if you're using a server or a Lambda, and your server goes down or your region goes down, so does your website. Cuz there's usually not a cached version, unless you add a cache control. But in most cases when you use SSR, you don't wanna use cache control.
[00:04:33] Because there shouldn't be a cached version cuz it's personalized on every request, or it should be. That's the best use case for server rendering. So that's definitely a downside. It's just more to maintain. Now, currently, a lot of people are also exploring with streaming server-side rendering. So the biggest difference here is with normal SSR, we had to create the entire HTML and fetch the entire bundle and parse this bundle before any hydration can begin.
[00:05:02] We had to wait for all the components to be ready before any component could be ready, really. While with streaming server rendering, the components get streamed as soon as they're generated on the server. So we see it can be generated in smaller parts, and also something called progressively hydrated.
[00:05:19] So whereas normal hydration, we had to wait for the entire bundle to be ready, parsed before the entire tree was hydrated. With progressive hydration, we can actually say, okay, just hydrate this component, just hydrate that component as soon as it's ready. So this is great for performance as we can instantly show our users like, okay, these smaller components are ready.
[00:05:40] So show them, don't wait for these larger components to generate on the server cuz that could end up in a bad time to first byte. So the performance here looks interesting. So as it streamed down, we don't really have one big, I guess the blue was, wait, I just gotta make sure of that.
[00:05:59] I guess that is parsing HTML. Yeah, so here, it parses the HTML layout panes and parses it again, layout pane, because it's constantly getting it. It's like a stream, which is great for, as you can see, the time to first byte is extremely fast because the smallest component can stream as soon as it's ready.
[00:06:14] And also the first contentful pane can be really fast because the first component can already render. And it can be interactive if it uses a progressive hydration. The largest contentful pane is still the same as with normal server-side rendering in most cases. Because we still have to wait for that entire component to be generated and then rendered, hydrated, all that stuff.
[00:06:37] Yeah, it's also great for the network backpressure. And the only downside is that the HTTP streaming is not supported on all runtimes yet. So in some cases, I believe that Lambda doesn't support it. I may be wrong here, but maybe you've deployed your server rendered app somewhere in a runtime that does support streaming.
[00:06:59] In that case, you can't use it. But yeah, that's really the only downside. Now, I didn't cover this here, but with the new React server components, this is actually a big part of that. Because streaming SSR kind of allows us to have a partially statically generated page, and then partially SSR page.
[00:07:16] Because we can SSR certain components. It's not like the entire page like we saw before. So we can static render the static parts of a page, which is great for performance. And then only server render any components that need that server-specific data. So that's very exciting.