Optimizing Page Speed With NextJs 🚀

Emre Yasin Çolakoğlu
May 31 · 6 min read

If your web pages open quickly, you give a strong first impression. A fast-loading webpage leaves visitors happy and satisfied. With a basic psychological assumption, people find fast-loading web pages more professional and trustworthy. Humankind has always related speed with efficiency.

Nevertheless, this psychological assumption is not unrelated to real-world data. The faster your website gets, the more visitors will visit your pages. You won’t be losing people who don’t want to wait and give up. On average, you are losing 40% of your visitors if your web pages open longer than 3 seconds.

Aside from your visitors, Google, which is practically the monopoly of search engines, announced that they will use these performance metrics as indicators for search engine rankings. Because of this, it's almost vital to have a fast-loading website.

In Kunduz, we are presenting samples of our questions and answers online to convey the Kunduz experience better to our students. These pages are invaluable in our efforts to reach wider audiences and persuade students to signup.

We believe in the motto “Release early, release often” here in Kunduz. Because of this, we never wait for a project to mature fully before releasing. We improve and develop in iterations. And lately, we have been improving this project, which is online since January 2021. Now let's see what we have been doing and how it affected our metrics.

Visuals 📸

As a Q&A platform, the images on our platform come in many dimensions, sizes, and formats. And this diversity sometimes causes issues for a website visitor. If you add a 2000x3000 pixels image with a 1.5 mb size to your webpages, your visitor will have a poor experience.

To fix this, we developed a solution that resizes, rescales, reformats, and refilters images on the fly using AWS Lambda Edge Functions. With this solution, clients can request images in specific dimensions, formats, and with/without various filters. In our web pages, we used images at 512px height and in WebP format. We also took into account that the width/height ratio shouldn’t be changed. This helped us reduce image sizes by 90% percent. And by using images with a fixed height we improved our CLS (Cumulative Layout Shift) score.

We also added loading=lazy to every image in our web pages except for the question image. This is because if we had lazyloaded our question image, we would hurt our LCP (Largest Contentful Paint) score. For the question image to load even faster, we used a technique called preloading so that the image would start downloading as soon as possible.

Lastly, we blurred our answer images to better protect our IP and increase our conversion rates.

Translations 🈯️

In a startup with global ambitions like Kunduz, we always take localization into account when we are developing new features and products. We use a third-party service for managing translations in our projects. Translations are mostly created by Product Managers before each task and then used by client teams during development.

We create our web translations under a single package and every web property in Kunduz uses the same package. Whether a student trying to purchase a Q&A package or a teacher trying to update their payment details use these translations from the same package.

Because of the nature of our toolset, NextJs, and next-i18next, these translations are added to the source of the pages as a javascript variable. This way, React can use these translations during the hydration phase. Including all of these translations, which grew over time, to each page request is a waste of resources. Students trying to see the answer to a question shouldn’t have to download a translation that is used to label a teacher's name input.

The change in the HTML size

To fix this, we grouped our translations in the third-party providers' control panel. And then we made developments to only include the required translation groups in our web pages. This helped us reduce our HTML size in half! A regular page that is used to be 130+kb is now 65+kb;

Http/2

Http/2 is a technology that is around for quite some time now. And somehow it slipped from our radar during the initial development phase. After a short config change in Nginx, we enabled it. This helped us increase our parallel request limit and shorten the time to load the website.

Nginx Cache 🧠

There will be times when you use every software development technique right and it just won’t be enough. While environmental factors like users' device capabilities, network quality, etc. can cause this, the tools you choose as a developer might be the culprit too.

For this project, our tool of choice was NextJs. We chose NextJs because we already have a solid React investment in knowledge and in-house components and the fact that it can do SSR (Server Side Rendering). But making a request to Kunduz APIs in order to retrieve data in every page visit took a little more time than we anticipated.

In order to improve the load times, we decided to implement Content Caching. This way, the HTML output is stored for 24 hours and the subsequent requests are served via Nginx, before even hitting our NextJs app. This development reduced our TTFB (Time to First Byte) metric from 1 second to 100 milliseconds. 🤯

Web Vitals 📈

Web Vitals are a series of quality metrics for measuring web experience, initiated by Google. Its subset, Core Web Vitals are the most important ones.

  • LCP (Largest Contentful Paint); measures page loading performance.
  • FID (First Input Delay); measures interactivity
  • CLS (Cumulative Layout Shift); measures visual stability.

We were tracking all these metrics from Google Search Console Tools and while it's a great tool, it didn’t provide us an instant feedback loop about our improvements.

So, we started to log every web vital to Google Analytics. It helped a great deal that NextJs was already measuring these metrics at every page load.

Now we can track real Web Vitals data from real website visitors instantaneously.

Other Developments 🗑

Some optimizations don’t affect performance directly. So there were some developments mostly made to satisfy measuring tools.

  • Adding alt tags to every image
  • Adding rel=noopener to every tag with an external URL
  • Converting every icon & image to SVG & WebP
  • Preloading every asset used from our CDN

We still have a lot to do in the accessibility area and we aim to address this soon.

And Final

With all these improvements, over the course of 1 May / 7 May;

  • Lowered FCP from 3.51 to 2.05
  • Lowered LCP from 3.42 to 2.07
  • Lowered TTFB from 2.98 to 1.16

While doing that, It was amazing to know that 65% of our visitors were using mobile devices that have somewhat limited CPU and network capabilities.

We certainly don’t feel like we reached the final stage with this project. At Kunduz, we believe in continuous learning and development. When and if there is a better tool/method/solution, we will be using it to provide a better experience for our students.

Thank you If you make it to this point. If you are also interested in Web technologies and want to be a part of this team, you can click this link reach out to us.

Kunduz, Inc.

Sharing experiments, gains and mistakes in the making of a long-lasting startup.

Kunduz, Inc.

Kunduz builds mobile services in the pursuit of making learning more accessible and smarter than ever. It serves students in Turkey, India, and the US. Posts in Turkish and/or English. Recommendations and questions are always welcome via contact@kunduz.com

Emre Yasin Çolakoğlu

Written by

Full Stack Web Developer from Istanbul / Turkey

Kunduz, Inc.

Kunduz builds mobile services in the pursuit of making learning more accessible and smarter than ever. It serves students in Turkey, India, and the US. Posts in Turkish and/or English. Recommendations and questions are always welcome via contact@kunduz.com