Skip to main content

Speeding Up Next JS Websites By Removing JavaScript

Jamstack is now more popular than ever due to its promise to deliver better performance and scalability than traditional server-rendered websites. Still, when comparing performance to a traditional server-rendered site, many Jamstack sites lose, leaving the end-users worse off.

Why is this happening?

Shouldn’t the Jamstack advantage of delivering HTML from CDN outperform everything?

The Modern Jamstack Approach

A big part of the typical Jamstack site is usually made with one of the popular front-end frameworks, like Next, Gatsby, or Nuxt. As all of these frameworks enable developers to create rich, interactive websites with pre-rendering of pages, the HTML is being pushed to the CDN edge.

With these frameworks comes fantastic flexibility for the frontend developer, but also a great responsibility. It’s important to know that the framework is doing two completely different things:

  1. Prerendering. Creating pre-rendered HTML pages, with CSS and JS, ready to be pushed to a CDN
  2. Interactivity. Making these pre-rendered pages come alive on the device by the use of the framework runtime Javascript

The Problem

The modern Jamstack approach looks like the best of both worlds, and in many cases, this is true.

There is, however, a hidden problem lurking beneath the surface.

A bunch of websites gets a big performance penalty in step 2, interactivity. It is often overlooked when developing a website since it typically affects mid-range devices on mobile networks, not what the typical developer is testing on.

How big is the problem? Let's use Pagespeed Insights as the tool to measure performance and the blog you are reading right now as an example. Here’s how it performs with framework enabled interactivity:

PageSpeed 63 score screenshot

A score of 63 is not terrible, but when looking at the lab results, it’s clear that we can do better.

PageSpeed detailed results screenshot

The Single Page Application (SPA)

We’re using Next.js and in this step, the framework JavaScript is downloaded and the application is rehydrated with the state coming from the server, essentially re-creating the HTML structure once more which enables Single Page Application (SPA) mode.

This takes up CPU resources on the device, as well as additional download costs as the framework files and application files need to be acquired. This process can take several seconds to complete and is especially prominent when the visiting user is on a mid-range mobile phone and on a mobile network.

Look what happens if we turn off step 2, and deliver just HTML and CSS:

PageSpeed 99 score screenshot

Now that's a massive difference. The reason it’s scoring so much better is that it no longer takes up that many resources on the device:

Lighthouse results details screenshot

Speed

Does enabling framework runtime JavaScript to justify the performance penalty?

In our case, it was easy to answer. No. The blog post you are reading is a barebone HTML document, sprinkled with a minimum amount of javascript to enable the few interactive things we have, like the main navigation.

This is what gives the best performance and user experience for our visitors.

Speed illustration

Users Don’t Want JavaScript

In an ecommerce store, users want to find and buy things. At a blog, users want to read.

Every website offers different things, and its front end should be tailor-made to serve a user experience best suited to its visitors. Frameworks with runtime JavaScript are just one way to enable that.

Take this website as an example. We still use Next.js for all the pages, enabling incremental static builds and the outstanding flexibility for composing user interfaces that React provides. We have made the decision to disable the framework runtime JavaScript for almost all pages, except the very few where it made sense to keep it.

Multichannel illustration

This article is not making an argument against a frontend framework running on a device. The approach is still great for:

  • Faster route transitions
  • Complex client-side logic
  • Development speed

How do you know when to do what? I would argue that if there is not a whole lot of complex interactivity, which admittedly is best handled by a frontend framework, then you should not enable the framework runtime JavaScript at all.

I invite you to use our Next.js eCommerce storefront boilerplate and play around with the capabilities of Next.js.