Updating Context will re-render context consumers, only in this example, it doesn’t
Github Repo is available for the demo app used in this article.
A Quick introduction to NextJS
Let’s talk about Web Performance
NextJS is a feature rich framework, and has many capabilities, however, we will be talking about the different pre-rendering options that make it a popular choice for many builders like myself. Of all its features, this is probably what makes it the most popular of the static site generators available today.
Comparison of the different pre-rendering options in NextJS
For this article, I have built a small project to illustrate these pre-rendering options. This article, like all the ones I have created in this website, are really future notes to myself disguised as blog posts. So I do hope that you will find these tips useful, as much as I had fun researching and trying them out.
If you want to follow along, please clone the above project to your local development environment and open the folder with VSCode.
In addition to the above project, we are also using an API that I have created for a past article when I was trying out GraphQL here. It is always cool to be able to build up on previous work, so whenever I can use these efficiencies, I take advantage of them.
This is the GraphQL API we are using in this exercise. Please play around with it and get familiar with the data.
So I needed an API and the quickest way for me was to use one that I already have deployed previously. I have wired up that GraphQL API here and used Apollo client to make is as quick and simple as possible.
Static Site Generation
First, let’s have a look at static generation in our sample NextJS application.
Have a play with the Static Generated Page and view source on the browser. Notice that what you see on your browser is what the crawlers see too, so its is excellent for SEO. However, since this page is generated at build time, the content may be stale, and you will need another build (and deploy) to keep your site current. Yes this is a hassle, but there are some strategies to cover us in this situation.
Just like GatsbyJS, NextJS supports static generation of content and this is the pre-rendering method that gives you the greatest improvement in page speed. This is in addition to the SEO benefits that make the page content available to the web crawlers. As the page is created ahead of time when the page is built, there is no speed penalty of the server creating the html content and sending it back to the clients.
Above shows a code snippet from the SSG page, showing that NextJS allows you to also get some data at build time (ie. using an API, read from DB, or from a file) in the process of generating the static html. NextJS makes this all possible using NextJS’
getStaticProps. This is a function that NextJS calls at build time, so all you have to do is return
props and that data will be available to your application.
The image above shows the complete html page come back to the client in 51.32 ms, super quick as this is the page that NextJS has pre-generated for us when the application was built by
next build. Core Web Vitals metrics - First Contentful Paint (FCP) and Largest Contentful Paint (LCP) comes back at 91.5 ms which is awesome, and Lighthouse did not detect any Layout Shift (LS) at all.
In NextJS, if all you have in your project is a static site, where you do not need any real time functionality, then you are set. All you really need to do is run the command
next build && next export and NextJS will build your static website where you can simply deploy this to any CDN, or even your S3 bucket or Blob storage. More info here about this functionality.
Server Side Rendering
This is where NextJS shines, of being able to serve content rendered on the server side. This used to be only possible with server side web frameworks like .Net and PHP, however this is well and truly possible in React, Now.
Check out our Server Side Rendered Page. If you have noticed, it still feels quick to load like our statically generated page in the previous section. And if you view source once again, it will be identical to its statically generated version.
The main difference is this method calls the API in real time, it calls the API the moment one loads the page. If you have a closer look at the image below, you will see that the page responds a bit slower at 374.82 ms, and FCP and LCP a bit slower at 418.8 ms, however, this is NOW server side rendering in real time. This delay accounts for the API call and NextJS building up the content on the server before responding the browser.
Client Side Rendering
The last topic for today’s article will be about client side rendering, and this is somewhat similar to normal React applications with a fundamental difference. By default, NextJS static generation for all pages. However, there are instances where one would like to avoid pre-rendering content.
Imagine you have an e-commerce site and you have logged in and looking at your shopping cart. You definitely would not want that information statically generated since that page contains personal information. You probably don’t need it server side generated too, since you will not need any SEO benefits in this case.
Another option is to employ client side rendering on this page. Since NextJS uses static generation by default, any page page that we create is pre-rendered by NextJS. Once the skeleton html has been mounted at the client, we can then re-hydrate it with our client side rendered code.
Have a play with our Client Side Rendered Page. You will notice that the header section displays instantly, while the F1 section towards the middle of the page displays after some small delay. That part is due to the client side rendering.
Instead of the usual flash of empty screen in a typical React application, we can display part of the application to the user and hydrate the UI with the rest using this client side rendering technique.
Image above shows the client rendered page in action. The statically rendered part returns to the browser in speedy 40.90 ms, and we have achieved FCP and LCP of 79.7 ms. However, notice the delayed call to the GraphQL API. Client side rendering is also an option where we can quickly return some content, then rehydrate to complete the page. Interestingly, Lighthouse is detecting a Layout Shift (LS) of 1265.1 ms and too many shifts on a page will adversely affect the Cumulative Layout Shift (CLS) metric for the page.
I have the client side code available here too. We have used
useEffect hook to ensure that we are calling the API only on the client side.
I wanted to explore NextJS to see what the fuss was all about. There is a reason why this React framework is one of the most popular out there now. I have seen the improvements in developer experience and the awesome convenience in its deployment options in Vercel, and in Serverless, for that matter. However this blog post is not about all that. Perhaps we will cover them in a future post.
For this post, we wanted to check out the pre-rendering options that NextJS offers. From static generation, which NextJS does automatically for all pages.
To server side rendering - no more will React be just a front end framework. NextJS has smartly merged NodeJs seamlessly so that we are NOW working on React Full Stack. How awesome is that, although there is a bit of mind shift there I do admit.
Lastly, we have covered client side rendering, which because it is still a React app after all, is still available as an option for us.
- The React Framework for Production
- Getting Started With Apollo Client in Next.js
- The Perils of Rehydration
Static Site Generation, Server Side Render or Client Side Render, what’s the difference?
How to ace your Core Web Vitals without breaking the bank, hint, its FREE! With Netlify, Github and GatsbyJS.
Follow along as I implement DynamoDB Single-Table Design - find out the tools and methods I use to make the process easier, and finally the light-bulb moment...
Use DynamoDB as it was intended, now!
A GraphQL web client in ReactJS and Apollo
From source to cloud using Serverless and Github Actions
How GraphQL promotes thoughtful software development practices
Why you might not need external state management libraries anymore
My thoughts on the AWS Certified Developer - Associate Exam, is it worth the effort?
Running Lighthouse on this blog to identify opportunities for improvement
Use the power of influence to move people even without a title
Real world case studies on effects of improving website performance
Speeding up your site is easy if you know what to focus on. Follow along as I explore the performance optimization maze, and find 3 awesome tips inside (plus...
Tools for identifying performance gaps and formulating your performance budget
Why web performance matters and what that means to your bottom line
How to easily clear your Redis cache remotely from a Windows machine with Powershell
Trials with Docker and Umbraco for building a portable development environment, plus find 4 handy tips inside!
How to create a low cost, highly available CDN solution for your image handling needs in no time at all.
What is the BFF pattern and why you need it.