Tips from open-source - How redirect in Next.js works under the hood

May 28, 2024 (6mo ago)

In this article, you will learn how redirect in next.js works under the hood by looking at the Next.js source code around redirect functionality.

My approach:

  1. Start from the import { redirect } from "next/navigation"'
  2. Back trace the redirect function to redirect.ts file
  3. redirect.ts explained
  4. How does throwing an error make the redirect work?
  5. Check redirect.test.ts to understand the full context
  6. redirect-boundary.ts has the redirect functionality

1. Start from the import:

Redirect function is imported from next/navigation. You can read more about redirect at: https://nextjs.org/docs/app/api-reference/functions/redirect.

But where do I find the next/navigation code? You can find this code in navigation.js. This file basically exports the navigation.ts that is /packages/next/src/client/components.

2. Back trace the redirect function to redirect.ts file

Although, navigation.ts has 272 lines of code at the time of writing this article, what we are interested in is the export of “redirect” at the end of the file as shown below. Focus on what you are looking for, don’t let the other code distract you.

As you can see, redirect is an export from navigation.react-server.ts. Inside the navigation.react-server.ts, you will find that redirect function is, in fact, from redirect.ts.

I did not know nested exports. Interesting.

3. Render.ts explained

“Invoking the redirect() function throws a NEXT_REDIRECT error and terminates rendering of the route segment in which it was thrown.” — Nextjs docs

Let’s look at the code snippet that throws the error inside redirect.ts

4. How does throwing an error make the redirect work?

Redirect function throws an error that sets the error.digest, but it was not obvious as to how throwing an error makes the redirect work.

I searched long and hard, my initial thoughts were around trying to find that catch block since redirect throws an error. I scoured the server related files but of no use.

I kept at it until it started to make sense when I looked at redirect.test.ts

5. Check redirect.test.ts to understand the full context

This one time I read somewhere that you could use tests to understand the context of a function. Hence the reason why I checked the code in redirect.test.ts

It is evident from the test code that getURLFromRedirectError(err) is called. You will find this function react-boundary.ts

Okay, test calls this getURLFromRedirectError function but what’s the execution flow? What happens after the error is thrown? Making a search based on getURLFromRedirectError function, the following are the results:

6. redirect-boundary.ts has the redirect functionality

The answer is Next.js redirect uses useRouter hook and depending on redirect type, it either pushes or replaces the url

This redirect-boundary is part of app-router code as shown below

when the error is thrown from redirect, it is caught by the redirect-boundary and redirect occurs. It is quite fascinating to find that redirect function itself does not do the redirect but rather redirect-boundary inside app-router handles the routing logic.

Conclusion:

I do not know why this API is designed this way but we could use this pattern of throwing an error from your npm package and use a boundary , preferably at the root level, to catch that error and do your thing.

If it wasn’t for me checking the redirect.test.ts code I would not have been able to figure out how the redirect works because I was hoping to find some sort out catch block in the redirect.ts but that is not the case.

Feel free to reach out to me at ramu.narasinga@gmail.com if you have any questions about this article.

Further reading:

  1. navigation.react-server.ts
  2. navigation.js
  3. redirect.ts
  4. redirect.test.ts
  5. redirect-boundary.tsx#L8