The source code for this blog is available on GitHub.
Note
Top

Rewrite and redirect in Next.js

Cover Image for Rewrite and redirect in Next.js
Chen Han
Chen Han

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 the allCategories 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 the filter method, which creates a new array with all elements that pass the provided test function.
  • The substring method was called on the custom_url.url property of each category, with an argument of 1, 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 the paths array. If it does, the request is rewritten using the NextResponse.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)
    );
}
© 2024 WOOTHINK. All Rights Reserved.
Site MapTerms and ConditionsPrivacy PolicyCookie Policy