Next.js Middleware: Advanced Use Cases and Examples

JavaScript Expert
April 12, 2024
Updated on November 19, 2024
0 MIN READ
#next-js#web-dev#react-native#architecture#next.js

Next.js Middleware: Advanced Use Cases and Examples

Next.js Middleware is a powerful feature that enables developers to execute code before a request is completed. It runs on the edge, providing low-latency responses for tasks like authentication, redirects, rewriting paths, and more. While basic middleware usage is well-documented, advanced use cases can unlock even greater potential for optimizing performance, security, and user experience.

In this post, we’ll explore advanced middleware techniques, including dynamic routing, A/B testing, bot detection, and performance optimization. Each section includes practical examples to help you implement these concepts in your Next.js applications.

Dynamic Routing and Conditional Redirects

Middleware allows you to inspect incoming requests and dynamically modify responses based on conditions like user authentication, geolocation, or device type. A common use case is redirecting users based on their locale or authentication status.

For example, suppose you want to redirect users to a login page if they’re not authenticated, but only for specific routes:

// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const { pathname } = request.nextUrl; const isAuthenticated = request.cookies.has('auth-token'); // Redirect unauthenticated users from protected routes if (pathname.startsWith('/dashboard') && !isAuthenticated) { return NextResponse.redirect(new URL('/login', request.url)); } // Redirect based on locale if (pathname === '/') { const locale = request.geo?.country?.toLowerCase() === 'fr' ? 'fr' : 'en'; return NextResponse.redirect(new URL(`/${locale}/home`, request.url)); } return NextResponse.next(); }

This middleware checks for an auth-token cookie before allowing access to /dashboard and redirects users to a locale-specific homepage based on their geolocation.

A/B Testing with Middleware

Middleware is an excellent tool for implementing A/B testing at the edge, ensuring fast response times without client-side flickering. You can split traffic between different page variants using cookies or random selection.

Here’s how you can route users to different versions of a page:

// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const { pathname } = request.nextUrl; if (pathname === '/landing') { // 50% chance to show variant B const variant = Math.random() > 0.5 ? 'b' : 'a'; const response = NextResponse.rewrite(new URL(`/landing/${variant}`, request.url)); // Set a cookie to maintain consistency response.cookies.set('ab-variant', variant); return response; } return NextResponse.next(); }

This example rewrites the request to /landing/a or /landing/b while storing the variant in a cookie to ensure a consistent experience for returning users.

Bot Detection and Crawler Optimization

Middleware can help identify bots and crawlers to serve optimized content (e.g., static HTML for SEO) or block malicious traffic. By inspecting the user-agent header, you can customize responses for search engines.

Here’s an example of bot detection:

// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; const BOT_USER_AGENTS = [ 'googlebot', 'bingbot', 'yandexbot', 'duckduckbot', ]; export function middleware(request: NextRequest) { const userAgent = request.headers.get('user-agent')?.toLowerCase(); const isBot = BOT_USER_AGENTS.some((bot) => userAgent?.includes(bot)); if (isBot && request.nextUrl.pathname === '/') { // Serve a pre-rendered static version for bots return NextResponse.rewrite(new URL('/static-seo', request.url)); } // Block suspicious user agents if (userAgent?.includes('malicious-bot')) { return new NextResponse('Access denied', { status: 403 }); } return NextResponse.next(); }

This middleware rewrites requests from known bots to a static SEO-optimized page while blocking malicious traffic.

Performance Optimization with Edge Caching

Middleware can improve performance by implementing custom caching strategies at the edge. For example, you can cache responses for authenticated users or bypass cache for dynamic content.

Here’s how to set cache headers dynamically:

// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const response = NextResponse.next(); // Cache public assets for 1 hour if (request.nextUrl.pathname.startsWith('/static')) { response.headers.set('Cache-Control', 'public, max-age=3600'); } // Disable cache for authenticated users if (request.cookies.has('auth-token')) { response.headers.set('Cache-Control', 'no-store'); } return response; }

This example caches static assets while ensuring authenticated users always receive fresh content.

Conclusion

Next.js Middleware unlocks advanced capabilities for routing, personalization, security, and performance optimization. By leveraging dynamic redirects, A/B testing, bot detection, and edge caching, you can build faster, more secure, and highly customizable applications.

Experiment with these techniques in your projects and explore the Next.js Middleware documentation for even more possibilities. Whether you're optimizing for SEO, improving user experience, or securing your app, middleware provides a flexible and powerful solution at the edge.

Share this article