Search code examples
reactjsnext.jsmiddlewarenext-auth

Next.js fails to build due to Dynamic Code Evaluation not allowed in Middleware


My Next.js project started failing to compile in build time once i introduced Next-auth dependency to handle social-login within providers (google) and credential login using email/password.

here's the log of the error during the build of the project

Failed to compile.

./node_modules/@babel/runtime/helpers/construct.js
Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Middleware pages/_middleware

Import trace for requested module:
./node_modules/@babel/runtime/helpers/wrapNativeSuper.js
./node_modules/next-auth/core/errors.js
./node_modules/next-auth/lib/logger.js
./node_modules/next-auth/react/index.js
./lib/apolloClient.ts
./lib/apollo.tsx
./src/service/serverFetcherQuery.ts
./src/pages/_middleware.ts

./node_modules/@babel/runtime/helpers/isNativeFunction.js
Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Middleware pages/_middleware

Import trace for requested module:
./node_modules/@babel/runtime/helpers/wrapNativeSuper.js
./node_modules/next-auth/core/errors.js
./node_modules/next-auth/lib/logger.js
./node_modules/next-auth/react/index.js
./lib/apolloClient.ts
./lib/apollo.tsx
./src/service/serverFetcherQuery.ts
./src/pages/_middleware.ts


> Build failed because of webpack errors

Searching similar issues online i found out that you cannot invoke GetSession() from next-auth in _middleware, that is not my case because i use my middleware to check the presence of a cookie:

/**
 * If the user doesn't have a theme-color cookie, set one
 * @param {NextRequest} req - NextRequest - The request object from Next.js
 * @returns A function that takes a NextRequest and returns a NextResponse
 */
export async function middleware(req: NextRequest) {
  const response = NextResponse.next()
  if (!req.cookies[COOKIE_NAME]) {
    const themeColors = await GetThemeServerSide()

    const nextUrl = req.nextUrl.clone()

    const responseWithCookie = NextResponse.rewrite(nextUrl)
    responseWithCookie.cookie(COOKIE_NAME, JSON.stringify(themeColors), {
      httpOnly: true
    })
    return responseWithCookie
  }
  return response
}

where GetThemeServerSide is a simple function that fetches a graphql query:

export const GetThemeServerSide = async () => {
  const { data }: { data?: GetThemeQuery } = await apolloClient.query({
    query: GET_THEME
  })
  return data?.theme?.data?.attributes
}

I use GetSession only in my apolloClient Link to insert The bearer token in Headers for next request

import { getSession } from 'next-auth/react'
const authLink = setContext(async (_, { headers }) => {
    if (typeof window !== 'undefined') {
      if (!token) {
        const session = await getSession()
        token = session?.accessToken as string
      }

      return {
        headers: {
          ...headers,
          authorization: token ? `Bearer ${token}` : ''
        }
      }
    }
    return {
      headers: {}
    }
  })

return new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: from([authLink, errorLink, httpLink]),
    ...other apollo related config
    })

version of npm packages:

 "dependencies": {
    "@apollo/client": "^3.5.10",
    "gql": "^1.1.2",
    "graphql": "^16.3.0",
    "next": "12.1.0",
    "next-auth": "^4.3.4",
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }

Solution

  • i figured it out, as juliomalves suggested that the apollo client auth link was the problem because the nextjs middleware is incapable of tree-shaking at the moment.

    I dedicated a new apollo client instance context free for all server-side graphql calls