Modern websites these days can look busy.
A lot of contents are crammed in one page.
Take a look at YouTube video page for example.
This page displays a lot of things:
- Main video information such as the actual video, the channel, and the video description
- Comments of this video
- Recommendations of similar video
In this post we’ll discuss about:
- How to implement this page with Next.js
- The performance issue we will face
- And how to fix that
Simple but slow approach
One straightforward way to render this page is by loading every data that will be displayed before rendering.
When using this technique, the page content will only be rendered once all of the three requests complete.
This technique while simple, can also impose some problems:
- It can feel slow. If one of the awaited functions take a lot of time to finish, the whole rendering process is stalled. In the recording below, it takes a while for the browser to load before it actually shows anything on the page.
- It is fragile. If the comments or recommendations failed to load, the whole page fails to load and will display an error instead. We will discuss on how to handle this in the next post.
Faster and safer rendering with Suspense streaming
Next.js provides a way to concurrently render page contents since App Router was released.
This is what Vercel does to reduce its perceived page load time.
In the recording above, there are two sections of data that are loaded and displayed independently.
Each section can render its data once loaded without having to wait for another section to finish.
How to render data in parallel
Let’s try to do the same thing with our YouTube example to improve rendering speed.
1. Split the data loading code
The first thing we need to do is to move the data loading code to each component.
If we try to put the server components as children of the page directly, the user still only sees the rendered content after all components have finished loading.
This is better than our initial code because the required data is loaded in parallel, but the rendering still happens at the same time after the data is loaded.
2. Render independently with Suspense
When we wrap React Server Components with Suspense
, the rendering process will start independently.
Any component that has finished loading data will render its contents and stream it to the user without having to wait for anything.
Let’s see how the rendering looks like after we implemented Suspense.
We immediately see something on the screen, and the sections are being loaded in parallel.
Any content that has finished loading is displayed immediately.