Next.js middleware.ts file executes twice (I think app renders twice as well)

Viewed 113

We're using the middleware and we just found out it executes things twice, even the application itself. I know that middleware is being used in resources as well, so I put a matcher and removed the "favicon" because I heard it can cause this bug.

When we use the middleware, and console.log in "_app.tsx", we see that it renders twice. Also I put a counter in middleware.ts and every page I enter I see that it increases the counter by two.

My middleware.ts page looks like:

import { NextRequest, NextResponse } from "next/server";

let counter = 0;
export function middleware(request: NextRequest) {
  const response = NextResponse.next();
  counter++;

  console.log("middleware #", counter);
  return response;
}

Github repo to reproduce: https://github.com/ornakash/reproduction-template-nextjs

I only see it twice in the server's terminal (in browser I see only one console.log). Do you have any idea why it happens?

1 Answers

You are using strict mode in React in your next.config.js file. From the documentation:

By intentionally double-invoking methods like the component constructor, strict mode makes patterns like this easier to spot.

Strict mode runs a lot of methods twice like constructor, componentWillMount, componentWillReceiveProps, componentWillUpdate, getDerivedStateFromProps, shouldComponentUpdate, render, setState, and updater functions.

I was also confused and asked a question. You should still be able to use strict mode - the extra render is fine. If you are trying to investigate why an extra render occurs (and console.log repeats), then you will be confused until you realize it because of strict mode. However, If strict mode is producing unexpected behaviors in the operation of your application (minus the extra render), you likely have a bug.

In production strict mode does not run code twice.


Edit: If you are sure this is not the issue... you should run a check to see if the double renders are from running first on the server SSR then on the client.

if (typeof window === 'undefined') {
    console.log('running on server');
} else {
    console.log('running on client');
}

Also I put a counter in middleware.ts and every page I enter I see that it increases the counter by two.

The above statement could be caused by strict mode, whereas the _app.tsx issue could be the SSR / client.

Related