· frameworks  · 5 min read

10 Next.js Tips You Didn't Know About: Unlocking Hidden Features

Discover 10 lesser-known Next.js features - from edge route handlers and middleware tricks to font optimization, smarter caching and streaming server components - that can meaningfully boost performance and developer experience.

Discover 10 lesser-known Next.js features - from edge route handlers and middleware tricks to font optimization, smarter caching and streaming server components - that can meaningfully boost performance and developer experience.

Introduction

Next.js is packed with features - some obvious, some hidden in the docs. This article highlights 10 lesser-known tips and patterns that can improve your app’s performance, UX and developer productivity. Each tip includes what it does, why it helps, and a practical example.

Tip 1 - Auto-optimized fonts with next/font

Why it helps

Serving fonts efficiently reduces layout shift and improves load time. next/font automatically optimizes font delivery and inlines critical CSS for your fonts.

How to use

// app/layout.jsx (App Router)
import { Inter } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
  display: 'swap',
});

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.variable}>
      <body>{children}</body>
    </html>
  );
}

Notes

  • Works with Google-hosted fonts and local fonts.
  • Avoid flash of invisible text by using display: 'swap' or other strategies.

Docs: https://nextjs.org/docs/basic-features/font-optimization

Tip 2 - Route handlers + Edge Functions for ultra-fast APIs

Why it helps

Route handlers (in the app directory) let you run server code with the Edge runtime, reducing latency by running close to users.

Example

// app/api/hello/route.js
export const runtime = 'edge'

export async function GET(request) {
  return new Response(JSON.stringify({ hello: 'from edge' }), {
    headers: { 'content-type': 'application/json' }
  })
}

When to use

  • Low-latency features like geolocation, authentication checks, or personalization.
  • Lightweight compute and fast response requirements.

Docs: https://nextjs.org/docs/app/building-your-application/routing/route-handlers

Tip 3 - Middleware for branching, A/B tests and smart caching

Why it helps

Middleware runs at the edge before a request reaches your app. Use it for redirects, A/B tests, locale routing, authentication gates, and altering request/response headers.

Example

// middleware.js
import { NextResponse } from 'next/server';

export function middleware(request) {
  const { pathname } = request.nextUrl;
  if (pathname.startsWith('/old-path')) {
    const url = request.nextUrl.clone();
    url.pathname = '/new-path';
    return NextResponse.rewrite(url);
  }
  return NextResponse.next();
}

Caveats

  • Runs on the Edge runtime - limited Node APIs.
  • Keep it fast and small to avoid adding latency.

Docs: https://nextjs.org/docs/advanced-features/middleware

Tip 4 - Use next/image’s AVIF/modern formats, priority, and fill

Why it helps

The next/image component optimizes images automatically (format, size, lazy loading). Choosing modern formats (AVIF/WebP), priority for LCP images, and fill for responsive backgrounds boosts perceived performance.

Example

import Image from 'next/image';

export default function Hero() {
  return (
    <div style={{ position: 'relative', height: '60vh' }}>
      <Image
        src="/hero.jpg"
        alt="Hero"
        fill
        priority // important for LCP
        sizes="(max-width: 768px) 100vw, 50vw"
      />
    </div>
  );
}

Docs: https://nextjs.org/docs/basic-features/image-optimization

Tip 5 - Incremental Static Regeneration (ISR) with precise revalidation

Why it helps

ISR keeps the benefits of static pages while allowing fresh content. In the App Router or fetch API, pass next: { revalidate: <seconds> } to control caching at a fine-grained level.

Example (App Router using fetch):

export default async function Page() {
  const res = await fetch('https://api.example.com/data', {
    next: { revalidate: 60 },
  });
  const data = await res.json();
  return <div>{/* render data */}</div>;
}

When to pick it

  • CMS-driven pages that update periodically.
  • Avoid rebuilding the whole site for content changes.

Docs: https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration

Tip 6 - Use next/script to control third-party scripts loading

Why it helps

Third-party scripts can block the main thread. next/script offers loading strategies (beforeInteractive, afterInteractive, lazyOnload) to prevent blocking and improve CLS/LCP.

Example

import Script from 'next/script';

export default function Analytics() {
  return (
    <>
      <Script
        src="https://example-cdn/analytics.js"
        strategy="lazyOnload"
        onLoad={() => console.log('analytics loaded')}
      />
    </>
  );
}

Docs: https://nextjs.org/docs/basic-features/script

Tip 7 - Dynamic import with SSR control and Suspense

Why it helps

Split heavy components into chunks, load them only when needed, and reduce initial bundle size. You can also opt out of SSR for components that only run in the browser.

Example

import dynamic from 'next/dynamic';
import { Suspense } from 'react';

const Map = dynamic(() => import('../components/Map'), { ssr: false });

export default function Page() {
  return (
    <Suspense fallback={<div>Loading map...</div>}>
      <Map />
    </Suspense>
  );
}

Docs: https://nextjs.org/docs/advanced-features/dynamic-import

Tip 8 - Streaming Server Components (App Router) for faster Time-to-First-Byte

Why it helps

Server components can stream HTML to the client as pieces become available. This reduces Time-to-First-Byte and allows the browser to start rendering earlier.

Pattern

  • Compose your UI as async server components.
  • Use suspense boundaries and smaller islands for client-side interactivity.

Example

// app/page.jsx
export default async function Page() {
  const posts = await fetch('...').then(r => r.json());
  return (
    <>
      <Header />
      <main>
        <Suspense fallback={<div>Loading posts...</div>}>
          <PostsList posts={posts} />
        </Suspense>
      </main>
    </>
  );
}

Docs: https://nextjs.org/docs/app/building-your-application/routing#server-components

Tip 9 - Fine-grained fetch caching and revalidation

Why it helps

Next.js’ built-in fetch integrates caching and revalidation options. Use next: { revalidate }, cache: 'force-cache', or cache: 'no-store' to control freshness per request rather than per page.

Example

// cache for 5 minutes
const res = await fetch('https://api.example.com/data', {
  next: { revalidate: 300 },
});

Why prefer this

  • Avoids large static rebuilds.
  • Lets you cache different data sources with different TTLs.

Docs: https://nextjs.org/docs/basic-features/data-fetching/fetching

Tip 10 - Rewrites, Redirects and Headers for security, SEO and CORS workarounds

Why it helps

Use rewrites to proxy API requests (avoid CORS), redirects for SEO changes, and headers to add security policies or caching rules without touching server code.

Example (next.config.js)

module.exports = {
  async rewrites() {
    return [
      {
        source: '/api/:path*',
        destination: 'https://third-party.example/:path*',
      },
    ];
  },
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [{ key: 'X-Frame-Options', value: 'DENY' }],
      },
    ];
  },
};

Docs: https://nextjs.org/docs/app/api-reference/next-config-js/headers-rewrites

Conclusion

These tips are practical ways to get more out of Next.js beyond the basics: faster pages with edge handlers, smarter fetching and caching, better third-party script handling, and modern font/image techniques. Try one or two on a small page first, measure before/after, and roll them into your app incrementally.

References

Back to Blog

Related Posts

View All Posts »
10 Angular Tips You Didn't Know You Needed

10 Angular Tips You Didn't Know You Needed

Discover 10 lesser-known Angular tips - from OnPush and trackBy to ngZone tricks, typed reactive forms, and standalone components - that will make your apps faster, safer, and easier to maintain.