Next.js Performance Optimization: From 60 to 98 on PageSpeed
The exact techniques we used to take a client's Next.js app from a 60 to a 98 PageSpeed score — covering images, fonts, bundle size, and Core Web Vitals.
Cherdung Infotech
Engineering Team
Why PageSpeed Scores Matter
Google uses Core Web Vitals as a ranking signal. A slow site doesn't just frustrate users — it costs you SEO. Here's how we systematically improved a client's Next.js app from a 60 to a 98.
The Audit
Start with data. Run your URL through:
- [PageSpeed Insights](https://pagespeed.web.dev)
- Chrome DevTools Lighthouse tab
- [web.dev/measure](https://web.dev/measure)
The three metrics that matter most: LCP (Largest Contentful Paint), CLS (Cumulative Layout Shift), and FID/INP (interaction responsiveness).
Fix 1: Images
Images are almost always the biggest culprit. Switch every <img> to Next.js <Image>:
import Image from 'next/image';
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={630}
priority // add this for above-the-fold images
/>This gives you: automatic WebP conversion, lazy loading, correct sizing, and no layout shift.
Fix 2: Fonts
Never load Google Fonts via a <link> tag in Next.js. Use next/font:
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'], display: 'swap' });This self-hosts the font, eliminates the render-blocking request, and removes the external DNS lookup.
Fix 3: Bundle Size
Run @next/bundle-analyzer to see what's bloating your JS:
npm install @next/bundle-analyzer
ANALYZE=true npm run buildCommon culprits: moment.js (use date-fns), lodash (use individual imports), large icon libraries (import only what you use).
Fix 4: Dynamic Imports
Heavy components that aren't needed on initial load should be lazy-loaded:
import dynamic from 'next/dynamic';
const HeavyChart = dynamic(() => import('./HeavyChart'), {
loading: () => <p>Loading...</p>,
ssr: false,
});Fix 5: Caching Headers
Add proper cache headers for static assets in next.config.ts:
headers: async () => [
{
source: '/images/(.*)',
headers: [{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }],
},
],Result
After applying these fixes: LCP dropped from 4.2s to 1.1s, CLS went to 0, and the overall score jumped from 60 to 98. The client saw a 23% increase in organic traffic over the next 60 days.
Need a performance audit for your app? [Talk to us](/contact).
Need help with your project?
We build web apps, mobile apps, and cloud systems for startups and businesses.
Book a free call