Rewrite and redirect in Next.js
Rewrite
In Next.js, the rewrite
method is a way to change the URL of a request before it is handled by the application. It can be used to redirect the request to a different URL, or to modify the pathname or other parts of the URL to match a specific pattern.
The rewrite
method is a part of the NextResponse
object, which is an object that represents the HTTP response that will be sent to the client. To use the rewrite
method, you can import the NextResponse
object from the next/server
module and then call the rewrite
method on it, passing in a new URL
object as an argument.
Here's an example of how the rewrite
method can be used to redirect a request to a different URL:
import { NextResponse } from 'next/server'
export async function middleware(request) {
if (request.nextUrl.pathname === '/old-page') {
return NextResponse.rewrite(new URL('/new-page', request.url))
}
}
In this example, the middleware
function is a middleware function that runs on the server side of a Next.js application. It checks the pathname of the request and, if it is /old-page
, it redirects the request to /new-page
using the NextResponse.rewrite
method.
You can also use the redirect
method of the NextResponse
object to redirect a request to a different URL. The redirect
method is similar to the rewrite
method, but it sends an HTTP redirect response to the client, telling the client's browser to navigate to a different URL. Here's an example of how the redirect
method can be used:
import { NextResponse } from 'next/server'
export async function middleware(request) {
if (request.nextUrl.pathname === '/old-page') {
return NextResponse.redirect('/new-page')
}
}
In this example, the middleware
function is again checking the pathname of the request, and if it is /old-page
, it redirects the request to /new-page
using the NextResponse.redirect
method.
import { NextResponse } from 'next/server'
import getAllCategories from "@/util/bigCommerce/getAllCategories";
// import { getSession } from "next-auth/client"
export async function middleware(request) {
/* http://localhost:3000/testRedirect */
if (request.nextUrl.pathname.startsWith('/testRedirect')) {
return NextResponse.rewrite(new URL('/', request.url))
}
const allCategories = await getAllCategories();
const paths = allCategories.map((cat) => "/" + cat.custom_url.url.substring(1));
if(paths.find(path => request.nextUrl.pathname.startsWith(path))) {
return NextResponse.rewrite(new URL('/category' + request.nextUrl.pathname, request.url))
}
}
- he first thing that was changed was the removal of an
if
statement that checked if the pathname of the request started with/testRedirect
. This part of the code was removed entirely. - The
getAllCategories
function was called and its result was stored in theallCategories
variable. This function retrieves a list of categories from a BigCommerce store. - The
allCategories
array was filtered to remove any category with a custom URL of/store
. This was done using thefilter
method, which creates a new array with all elements that pass the provided test function. - The
substring
method was called on thecustom_url.url
property of each category, with an argument of1
, to remove the leading/
character. This was done to create an array of paths that can be used to match against the pathname of the request. - The final change was to the
if
statement that checks if the pathname of the request starts with any of the paths in thepaths
array. If it does, the request is rewritten using theNextResponse.rewrite
method to add the/category
prefix to the pathname.
Overall, the changes made to the code involve a refactoring of the logic used to handle requests for category pages. Instead of using a catch-all route at the root level of the application, the code uses middleware to rewrite the request and place it inside a /category
directory. This allows the application to handle category pages without affecting other pages or the SEO URL structure.
import { NextResponse } from "next/server";
import getAllCategories from "@/util/bigCommerce/getAllCategories";
export async function middleware(request) {
// Problem: Cannot place Catch-All route for category urls in root directory without affecting other pages.
// Cannot move Catch-All route inside a directory natively without affecting SEO URL structure.
// Solution: Use middleware to rewrite Catch ALL Routes inside a category directory.
const allCategories = await getAllCategories();
// Remove store category. Handled differently with dynamic routes
const noStore = allCategories.filter(
(cat) => cat.custom_url.url !== "/store"
);
//
const paths = noStore.map((cat) => "/" + cat.custom_url.url.substring(1));
if (paths.find((path) => request.nextUrl.pathname.startsWith(path)))
return NextResponse.rewrite(
new URL("/category" + request.nextUrl.pathname, request.url)
);
}