Mark Ku's Blog
Podcast ConversationAI dialogue version of this article · Mandarin audio
Audio for this article is powered by VoAIVoAI

Introduction

After working with the Next.js framework for over two years, I figured it was time to put together a list of the performance optimizations we have applied. Next.js itself does a lot of work to optimize JavaScript builds and images.

1. Image optimization

  • Next.js already does plenty out of the box: lazy loading, image-loader optimizations (resizing, format conversion, quality compression), and serving different sizes based on the user's resolution. Just by using next/image correctly, you get image optimization for free.
  • Move images to a CDN, and switch the Next.js loader to a third-party image loader.

2. Reduce JS size and shrink the bundle

  • Next.js does code splitting automatically. Anything used in the shared _app.tsx or layout ends up in the main JS bundle. Move it down to subpages so it does not get bundled into the main JS.
  • Pages should only render the components they actually need. Use dynamic import for components only used by the current page so they are not bundled into the main JS.
import dynamic from 'next/dynamic';
const CartView = dynamic(() => import('./cartView'));
  • On the server side, only fetch the data the page needs and avoid sending unnecessary data to the client.
  • Use next/bundle-analyzer to identify oversized packages, and replace them with lighter alternatives, e.g. Moment.js to Day.js.
  • The way you import packages also impacts the bundle size, e.g. lodash:
import  throttle from 'lodash/throttle'; // good
import { throttle } from 'lodash'; // bad

  • JS or CSS that is not required for the initial render should be loaded on demand to avoid blocking the first render. The shopping cart side panel is a good example.

3. Reduce CSS size.

  • Move shared CSS that is not needed on every page into individual pages or components, and remove unused CSS.
  • Replace heavyweight CSS frameworks such as Bootstrap.

4. Use Jenkins to push static files to a CDN. The CDN reduces I/O load on the origin server, and you can enable client-side caching at the CDN edge.

5. Reduce layout shift and jitter during page rendering, since Google penalizes this.

6. Apply font-display: swap so a fallback font is shown while the web font is loading.

7. Audit and remove unused third-party JS. JS that is only required after user interaction can be loaded later, avoiding loading too much JS during the first render and blocking the main thread.

  <Script
   src="https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js"
   strategy="afterInteractive"
  ></Script>

(Loading JS only after the user scrolls would likely be even better, but it depends on the requirement.)

8. Tune transport and compression protocols (Brotli), and enable HTTP/2 and HTTP/3 for faster delivery and better compression efficiency.

9. Reduce request count and shrink API responses. Cache backend data that rarely changes but is queried frequently.

10. Server rendering is expensive. Where possible, use SSG or ISR; pages that do not need pre-rendering can be CSR. When rendering, prefer reading from Redis over hitting the API — Redis is always faster.

11. Use an LTM and multiple machines/instances to spread the load.

12. Upgrade to the App Router and use server components, so non-interactive components do not get bundled into client-side JS.

13. Upgrade Next.js regularly. Each release claims performance improvements, and while every upgrade brings minor pain, skipping upgrades for too long makes future upgrades much harder.

Author

Mark Ku

擁有 10+ 年經驗的資深軟體工程師,現為 AI 應用 Builder,專注於大型平台架構與簡化複雜系統設計,從電商系統到訂閱與收費平台,結合 AI Agent、AI 整合與自動化開發,打造高效率且可持續演進的產品技術基礎。Read More

Found this useful?

The author's free tools, daily podcasts and newsletter are all here.

Mark Ku · This article is licensed under CC BY 4.0. Credit the author and link back to the original when reusing it.

Comments

Subscribe to Newsletter

Subscribe to get new posts delivered instantly — never miss a tech share.

By submitting, you agree to receive emails. You can anytime.

Popular Posts

View all
Mark Ku
··602

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution
Mark Ku
··492

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.
Mark Ku
··334

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki
Mark Ku
··268

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning
Mark Ku
··218

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1
Mark Ku
··217

Setting Up Samba on Ubuntu to Share Folders with Windows 11

Setting Up Samba on Ubuntu to Share Folders with Windows 11
這些年對 Next.JS 做過的網站效能優化 - Mark Ku's Tech Notes