Next.js Performance Optimization
📌 Introduction to Next.js Performance Optimization
Next.js provides server-side rendering (SSR), static site generation (SSG), and client-side rendering (CSR) to improve performance. This guide covers best practices to optimize a Next.js application for speed and efficiency.
🔹 1. Image Optimization with next/image
Next.js has built-in automatic image optimization using next/image
.
✅ Use next/image
instead of <img>
for optimized images:
import Image from "next/image";
export default function Home() {
return <Image src="/example.jpg" alt="Example" width={500} height={300} priority />;
}
✅ Benefits:
- Lazy loading (only loads images when needed).
- Automatic resizing for different screen sizes.
- WebP support for better compression.
🔹 2. Optimize Fonts with next/font
Next.js provides automatic font optimization.
✅ Use Google Fonts with built-in Next.js font optimization:
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
export default function Home() {
return <p className={inter.className}>Optimized Font</p>;
}
✅ Benefits:
- No FOIT (Flash of Invisible Text).
- Loads only required font subsets.
🔹 3. Use Static Site Generation (SSG) When Possible
SSG pre-renders pages at build time, making them blazing fast.
✅ Use getStaticProps
for static pages:
export async function getStaticProps() {
const res = await fetch("https://api.example.com/posts");
const posts = await res.json();
return { props: { posts }, revalidate: 60 }; // ISR (Incremental Static Regeneration)
}
✅ When to use SSG?
- Content does not change frequently (e.g., blogs, landing pages).
- You need fast initial load times.
🔹 4. Use Server-Side Rendering (SSR) Only When Necessary
SSR generates pages on each request, which can slow down performance.
✅ Use getServerSideProps
for dynamic data fetching:
export async function getServerSideProps() {
const res = await fetch("https://api.example.com/user");
const user = await res.json();
return { props: { user } };
}
✅ When to use SSR?
- When real-time data is needed (e.g., dashboards, authenticated pages).
❌ Avoid SSR for static pages to prevent unnecessary re-renders.
🔹 5. Enable Compression & Caching
✅ Use Gzip or Brotli compression for faster asset delivery.
In next.config.js
, enable compression:
module.exports = {
compress: true,
};
✅ Use HTTP caching headers:
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
🔹 6. Reduce JavaScript Bundle Size
✅ Analyze your Next.js bundle using Webpack Bundle Analyzer:
npm install --save-dev @next/bundle-analyzer
In next.config.js
:
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
});
module.exports = withBundleAnalyzer({});
Run the analyzer:
ANALYZE=true npm run build
✅ Remove unnecessary libraries and optimize imports:
// ❌ Bad - Imports everything
import * as lodash from "lodash";
// ✅ Good - Import only needed functions
import debounce from "lodash/debounce";
🔹 7. Code Splitting & Lazy Loading
✅ Use React Dynamic Imports for Lazy Loading Components:
import dynamic from "next/dynamic";
const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
ssr: false, // Only load on client-side
});
✅ Benefits:
- Reduces initial JavaScript load.
- Loads components only when needed.
🔹 8. Optimize API Requests
✅ Use SWR for client-side data fetching & caching:
import useSWR from "swr";
const fetcher = (url) => fetch(url).then((res) => res.json());
export default function Dashboard() {
const { data, error } = useSWR("/api/data", fetcher);
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return <div>{data.message}</div>;
}
✅ Use Incremental Static Regeneration (ISR) to Refresh Data:
export async function getStaticProps() {
return { props: { data }, revalidate: 60 }; // Re-generates every 60 seconds
}
✅ Batch API requests instead of sending multiple fetch requests:
const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]);
🔹 9. Optimize CSS & Reduce Unused Styles
✅ Use Tailwind CSS for minimal CSS footprint:
npm install tailwindcss postcss autoprefixer
npx tailwindcss init -p
✅ Enable PurgeCSS to remove unused styles in production:
In tailwind.config.js
:
module.exports = {
purge: ["./pages/**/*.tsx", "./components/**/*.tsx"],
};
✅ Use @layer
to minimize unused styles:
@layer base {
h1 {
font-size: 2rem;
}
}
📌 Conclusion
Optimizing a Next.js application involves efficient rendering strategies, image & font optimization, caching, lazy loading, and reducing bundle sizes. Following these best practices will improve performance, SEO, and user experience. 🚀