Advanced Middleware Documentation in Next.js
This document provides a detailed overview of implementing internationalization (i18n) and authentication middleware in Next.js applications. These middleware enhance user experience by ensuring content is delivered in the user's preferred language and secure access to protected routes.
Packages Versions​
"@formatjs/intl-localematcher": "^0.5.4",
"negotiator": "^0.6.3",
"next": "^13.4.18",
"next-auth": "^4.24.5",
Internationalization Middleware (withI18nMiddleware) Detailed Explanation​
This section delves into the withI18nMiddleware, a crucial component for managing internationalization in a Next.js application. It automatically detects the user's preferred language and redirects the request to a URL that includes the detected locale, enhancing the application's usability across different regions.
Locale Detection and Redirection​
Detecting the User's Locale: The middleware employs the
Negotiatorlibrary and@formatjs/intl-localematcherto determine the best match for the user's preferred language based on the request headers. This process ensures that the application serves content in a language that best fits the user's preference.import { NextRequest } from "next/server";
import { i18n } from "i18n.config";
import { match as matchLocale } from "@formatjs/intl-localematcher";
import Negotiator from "negotiator";
function getLocale(request: NextRequest): string | undefined {
const negotiatorHeaders: Record<string, string> = {};
request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));
const locales: string[] = i18n.locales;
const languages = new Negotiator({ headers: negotiatorHeaders }).languages();
const locale = matchLocale(languages, locales, i18n.defaultLocale);
return locale;
}Redirecting Based on Locale: After determining the preferred locale, the middleware checks if the requested URL already includes this locale. If not, it redirects the user to the correct URL that includes the preferred locale, ensuring that the user receives content in the correct language.
export function withI18nMiddleware(middleware: CustomMiddleware) {
return async (request: NextRequest, event: NextFetchEvent, response: NextResponse) => {
const pathname = request.nextUrl.pathname;
const pathnameIsMissingLocale = i18n.locales.every(
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
);
if (pathnameIsMissingLocale) {
const locale = getLocale(request);
return NextResponse.redirect(new URL(`/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`, request.url));
}
return middleware(request, event, response);
};
}
Conclusion​
The withI18nMiddleware is integral for creating a globally accessible Next.js application, seamlessly managing language preferences to deliver a localized user experience. By utilizing advanced locale detection and redirection techniques, it ensures that users are always served content in their preferred language, contributing to a more inclusive and user-friendly application.
Authentication Middleware with NextAuth​
Authentication middleware in Next.js ensures that only authenticated users can access specific routes, redirecting others to a login page.
Purpose​
Secures paths by requiring users to be authenticated, using NextAuth for session management and token validation.
Implementation​
The middleware checks for a valid session token using `getToken` from `next-auth/jwt`. If a token is not present, indicating the user is not authenticated, they are redirected to a sign-in page.
Code Example​
import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';
export async function withAuthMiddleware(request) {
const token = await getToken({ req: request });
if (!token) {
// Redirect to sign-in page
return NextResponse.redirect('/auth/signin');
}
return NextResponse.next();
}
Key Benefits​
- Enhances security by protecting sensitive routes.
- Provides a seamless user experience by redirecting unauthenticated users to the login page.
Middleware Chaining​
Overview​
Combining multiple middleware functions into a single sequence allows for layered and modular handling of requests.
Benefits​
- Simplifies complex middleware logic by structuring it into manageable, reusable components.
- Enhances code readability and maintainability.
Conclusion​
Implementing these middleware in a Next.js application significantly improves user experience through personalized content delivery and secure access management. By leveraging Next.js's middleware capabilities, developers can create more dynamic, secure, and user-friendly web applications.