#Why is middleware called multiple time ?

1 messages · Page 1 of 1 (latest)

raw needleBOT
#

Hi @lusty apex. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The behavior you're observing is due to the way Next.js handles requests. Middleware in Next.js is invoked for every route in your project, and it runs before cached content and routes are matched. This means that it can be called multiple times for a single page load, especially if there are multiple resources (like images, scripts, etc.) being loaded for that page.

In addition, there are some known issues with Next.js middleware executing multiple times. For instance, a Github issue (https://github.com/vercel/next.js/issues/39917) was raised where middleware was found to execute twice, even when using a matcher. This was particularly problematic when executing fetches or stateful logic in middleware.

To avoid this, you can use the matcher in the middleware configuration to specify which paths the middleware should run on. This can help guard against execution of middleware for non-user-initiated calls.

Here's an example of how to use a matcher:

export const config = {
  matcher: '/about/:path*',
}

In this example, the middleware will only run for paths that start with /about.

For more information, you can refer to the Next.js Middleware documentation (https://nextjs.org/docs/app/building-your-application/routing/middleware).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@lusty apex kapa.ai is still learning and improving, please let us know how it did by reacting below

lusty apex
#

@raw needle is it possible to have multiple middleware ?

raw needleBOT
#

Let me check the knowledge base for you. One moment! :books:

#

No, it's not possible to have multiple middleware in Next.js. As per the Middleware Upgrade Guide (https://nextjs.org/docs/messages/middleware-upgrade-guide#explanation), Next.js has moved from supporting nested middleware to a single root middleware. This change was made based on customer feedback and provides several improvements:

  • Faster execution with lower latency: A single middleware means a single function execution, which is more efficient.
  • Less expensive: Middleware usage is billed per invocation. A single middleware means a single invocation per request and is more cost-effective.
  • Middleware can conveniently filter on things besides routes: By moving to a single root middleware, you can execute middleware based on other conditions, like cookies or the presence of a request header.
  • Deterministic execution ordering: Moving to a single, root middleware more explicitly defines execution order.
  • Supports Next.js Layouts (RFC): Moving to a single, root middleware helps support the new Layouts (RFC) in Next.js.

You should declare one single Middleware file in your application, which should be located next to the pages directory and named without an _ prefix. Your Middleware file can still have either a .ts or .js extension. Middleware will be invoked for every route in the app, and a custom matcher can be used to define matching filters.

Here's an example of how to define a middleware:

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
 return NextResponse.rewrite(new URL('/about-2', request.url))
}
 
// Supports both a single string value or an array of matchers
export const config = {
 matcher: ['/about/:path*', '/dashboard/:path*'],
}
#

In this example, the middleware will only run for paths that start with /about or /dashboard.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@lusty apex kapa.ai is still learning and improving, please let us know how it did by reacting below

lusty apex
#

@raw needle why do we need to include the "request.url" in the redirect function here
export function middleware(request: NextRequest) {
console.log('middleware called');
if (request.nextUrl.pathname.startsWith('/about')) {
return NextResponse.redirect(new URL('/', request.url));
}
}

raw needleBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The request.url is used as the base URL when creating a new URL object in the NextResponse.redirect() function.

In the context of the URL constructor, the second parameter is the base URL string. The base URL is used to resolve the relative URL when the input is a relative URL.

In your case, new URL('/', request.url) is creating a new URL object with '/' as the relative URL and request.url as the base URL. This means it will redirect to the root path of the current base URL (which is the URL of the current request).

Here's the code snippet for reference:

export function middleware(request: NextRequest) {
  console.log('middleware called');
  if (request.nextUrl.pathname.startsWith('/about')) {
    return NextResponse.redirect(new URL('/', request.url));
  }
}

For more information, you can refer to the Next.js Middleware documentation (https://nextjs.org/docs/app/building-your-application/routing/middleware).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: