Aug 26, 2022

How to improve Next.js App performance with code splitting and lazy hydration

alen-kalajevac-blog

This article was written by Anel Kalajevac, Technical Lead at HTEC Group

When we talk about web applications, everything comes down to performance. Except for the user experience, web application performance has an impact on bounce rates, conversion rates, and ranking in organic search. In other words, slow web applications will hurt your brand and cost you money. There are many reasons why a web application may load slowly and many different approaches to improve performance. I’m going to show you how to improve the performance of Next.js-based applications by using the code splitting technique and lazy hydration. But first, let’s see what affects web application performance. 

What affects web application performance? 

The most common reasons why web application load time might be lagging are: 

  • Heavy JavaScript usage 
  • Large image sizes 
  • Not using browser cache 
  • Too many plugins and external libraries 
  • Slow network connection 
  • Older browsers 
  • Poor hosting plan 

I’m going to focus on heavy JavaScript usage, but first, let’s see how to test web application performance. 

How to test web application performance? 

Many different tools can be used for checking web application performance, but all of them are measuring mainly the same metrics. Alongside many different metrics, the most important are Largest Contentful Paint, First Input Delay, and Cumulative Layout Shift. These metrics are also defined as Core Web Vitals by Google. 

For web application performance checking I prefer using PageSpeed Insights, which provides a nice report for mobile and desktop devices. The report includes a general score calculated by Lighthouse Scoring Calculator, results for different metrics, and suggestions for improvements.  

The metrics scores and the performance score are colored according to these ranges: 

  • 0 to 49 (red): Poor. 
  • 50 to 89 (orange): Needs Improvement. 
  • 90 to 100 (green): Good. 

Now, when we know how to test web application performance, let’s see how it can be improved. 

Example 

Let’s say that we have a web application created by using React and Next.js framework. PageSpeed Insights reports two main issues:  

  • Reduce unused JavaScript. 
  • Minimize main-thread work. 

Idea 

Reducing unused JavaScript by splitting the main JavaScript file shared by all pages could be a good starting point, but can we go one step further? Do we need all that JavaScript during the initial load of the page? Why download the footer code if the user during the initial page load can’t see the footer? 

So, the idea is to load only JavaScript code relevant to the visible part of the page, and the rest will be loaded as the user scrolls down. This will reduce unused JavaScript and minimize main-thread work. 

Solution 

There are five core parts of implementation: 

  1. A webpack plugin for changing module ids. 
  2. Next.js plugin for marking lazy modules. 
  3. Custom Next.js document. 
  4. Next.js dynamic import. 
  5. Component for lazy hydration (library or custom implementation based on Intersection Observer API). 

 

First, I will create a webpack plugin to change the module id. 

Then, I will create a Next.js plugin to mark target modules as lazy and merge a webpack configuration with the Next.js configuration. This plugin will find defined modules for lazy loading and add the prefix “lazy” to the module id. For this purpose, I will use the previously created webpack plugin for changing module ids. The prefix “lazy” is an indicator that the module should be lazy-loaded when it is necessary. In the example below, I’ve defined the footer component as a lazy module. 

Now, when I have a logic that marks the footer component as a lazy module, the next step is a modification of Next.js internals within _document.tsx. I will extend next/head to skip printing <script> tags for lazy JS chunks into a document. Also, I will modify NextScript to let a webpack manage the loading of dynamic ids. 

The mechanism for excluding configured lazy chunks from the initial page load is implemented, so the last step is the dynamic import of configured lazy module (component) with a lazy hydration wrapper. Dynamic import is just an extension of React.lazy that helps us with code splitting. By using dynamic import, the footer component in our case will not be included in the page’s initial JavaScript bundle. For lazy hydration, I can use some of the existing libraries or create a custom solution called LazyHydration based on Intersection Observer API. 

As soon as I scroll near the footer component, webpack will download the dynamic import and LazyHydration will hydrate it into interactive react code. 

Summary 

Optimizing web application performance is a challenging undertaking that depends on speed test results and reported issues. Code splitting and lazy hydration can reduce your page weight and improve performance if you have issues with heavy JavaScript usage. When optimizing web application performance, the most important thing before taking any steps is looking through speed test results and focusing on high-impact factors. 

 

 

 

Author
Nebojsa Cato, Senior Content Writer, HTEC Group
Nebojsa Cato

Hiya! I am Nebojša, in-house writer at HTEC. I am constantly fascinated by the people and the technology around me, and I love bringing their stories out to the surface. Also, you are awesome and I wish you a glorious day!

Related articles:

Ai continues to change BLOG
Tech Blog
October 12, 2021

How to Build a Testing Pyramid

htec-mobility-gps
Tech Blog
April 20, 2021

The Future of Mobility as a Service (MaaS)

Digital Retail Trends
Tech Blog
April 19, 2021

Digital Retail Trends — Digest #15

How to block cookies?

You can change your cookie preferences at any time by clicking on the ‘Cookie preferences’ icon. You can then adjust the available sliders/checkboxes to ‘On’ or ‘Off’, then clicking ‘Save and close’. You may need to refresh your page for your settings to take effect.

essential cookies
preference cookies
statistic cookies
marketing cookies
Read more about these cookies