Middleware no Next.js 16 em 2026: Edge Runtime, Autenticação e Perguntas de Entrevista

Domine o middleware do Next.js 16 com Edge Runtime, padrões de autenticação e perguntas técnicas de entrevista para desenvolvedores frontend.

Middleware do Next.js 16 com Edge Runtime e autenticação

O middleware do Next.js 16 é executado antes de cada requisição, tornando-se a primeira linha de defesa para autenticação, localização e manipulação de requisições. Compreender o funcionamento do middleware é essencial para construir aplicações de produção e constitui um tema frequente em entrevistas técnicas de frontend.

O Middleware executa no Edge

O middleware do Next.js 16 é executado no Edge Runtime por padrão, o que significa que funciona em data centers próximos aos usuários com cold starts inferiores a um milissegundo. Isso o torna ideal para verificações de autenticação e redirecionamentos que precisam ocorrer antes da página ser renderizada.

Como o Middleware do Next.js 16 Funciona Internamente

O middleware no Next.js 16 intercepta as requisições antes que elas cheguem ao handler de rota ou ao componente de página. O arquivo de middleware deve ser colocado na raiz do projeto (ao lado de app/ ou pages/) e exporta uma função padrão que recebe um objeto NextRequest.

A restrição do Edge Runtime significa que o middleware não pode utilizar APIs do Node.js como fs ou Buffer. Ele executa em isolates V8, similar ao Cloudflare Workers, o que permite distribuição global mas limita as APIs disponíveis aos padrões Web.

middleware.tstypescript
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  // Acesso aos headers, cookies e URL da requisição
  const token = request.cookies.get('session')?.value
  const pathname = request.nextUrl.pathname

  // Log para debugging (visível nos logs da Vercel)
  console.log(`Middleware: ${request.method} ${pathname}`)

  // Continua para o handler de rota
  return NextResponse.next()
}

// Configura quais caminhos acionam o middleware
export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}

A configuração matcher utiliza uma sintaxe similar a regex para definir quais caminhos acionam o middleware. Sem essa configuração, o middleware executa em cada requisição, incluindo assets estáticos.

Padrões de Autenticação com Middleware do Next.js

O middleware se destaca na proteção de rotas que requerem autenticação. Em vez de verificar a autenticação em cada componente de página, uma verificação centralizada no middleware garante que nenhuma rota protegida possa ser acessada sem uma sessão válida.

middleware.tstypescript
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const protectedRoutes = ['/dashboard', '/settings', '/profile']
const authRoutes = ['/login', '/register']

export function middleware(request: NextRequest) {
  const token = request.cookies.get('session')?.value
  const pathname = request.nextUrl.pathname

  // Verifica se a rota requer autenticação
  const isProtectedRoute = protectedRoutes.some(route => 
    pathname.startsWith(route)
  )
  const isAuthRoute = authRoutes.some(route => 
    pathname.startsWith(route)
  )

  // Redireciona usuários não autenticados para a página de login
  if (isProtectedRoute && !token) {
    const loginUrl = new URL('/login', request.url)
    loginUrl.searchParams.set('callbackUrl', pathname)
    return NextResponse.redirect(loginUrl)
  }

  // Redireciona usuários autenticados para fora das páginas de auth
  if (isAuthRoute && token) {
    return NextResponse.redirect(new URL('/dashboard', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}

Esse padrão lida tanto com a proteção de rotas quanto com a prevenção de acesso às páginas de login para usuários já autenticados.

Validação JWT no Middleware Edge

Validar tokens JWT no edge requer bibliotecas compatíveis com Edge Runtime. O pacote jose é a escolha padrão porque utiliza as APIs Web Crypto disponíveis no ambiente Edge.

lib/auth-edge.tstypescript
import { jwtVerify } from 'jose'

const JWT_SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || 'your-secret-key'
)

export async function verifyToken(token: string) {
  try {
    const { payload } = await jwtVerify(token, JWT_SECRET)
    return { valid: true, payload }
  } catch (error) {
    return { valid: false, payload: null }
  }
}
middleware.tstypescript
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { verifyToken } from './lib/auth-edge'

export async function middleware(request: NextRequest) {
  const token = request.cookies.get('auth-token')?.value

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  const { valid, payload } = await verifyToken(token)

  if (!valid) {
    // Remove o cookie inválido e redireciona
    const response = NextResponse.redirect(new URL('/login', request.url))
    response.cookies.delete('auth-token')
    return response
  }

  // Adiciona informações do usuário aos headers para Server Components
  const requestHeaders = new Headers(request.headers)
  requestHeaders.set('x-user-id', payload?.sub as string)
  requestHeaders.set('x-user-role', payload?.role as string)

  return NextResponse.next({
    request: { headers: requestHeaders },
  })
}

Passar informações do usuário através de headers permite que Server Components acessem dados de autenticação sem consultas adicionais ao banco de dados.

Gerenciamento de Internacionalização no Middleware

O middleware é o local ideal para lidar com detecção de idioma e redirecionamentos. O Next.js 16 fornece helpers integrados para internacionalização que funcionam no Edge Runtime.

middleware.tstypescript
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'

const locales = ['en', 'fr', 'de', 'es', 'ja']
const defaultLocale = 'en'

function getLocale(request: NextRequest): string {
  const negotiatorHeaders: Record<string, string> = {}
  request.headers.forEach((value, key) => {
    negotiatorHeaders[key] = value
  })

  const languages = new Negotiator({ headers: negotiatorHeaders }).languages()
  return match(languages, locales, defaultLocale)
}

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname

  // Verifica se o pathname já tem um locale
  const pathnameHasLocale = locales.some(
    (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
  )

  if (pathnameHasLocale) return NextResponse.next()

  // Redireciona para o pathname com locale
  const locale = getLocale(request)
  const newUrl = new URL(`/${locale}${pathname}`, request.url)
  
  return NextResponse.redirect(newUrl)
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}

Rate Limiting no Edge

Implementar rate limiting no middleware protege as APIs contra abusos. Contadores em memória não funcionam de forma confiável no edge devido à natureza distribuída, mas soluções externas como Upstash Redis fornecem armazenamento compatível com Edge.

middleware.tstypescript
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'

const redis = new Redis({
  url: process.env.UPSTASH_REDIS_URL!,
  token: process.env.UPSTASH_REDIS_TOKEN!,
})

const ratelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(10, '10 s'),
  analytics: true,
})

export async function middleware(request: NextRequest) {
  // Limita apenas rotas de API
  if (!request.nextUrl.pathname.startsWith('/api')) {
    return NextResponse.next()
  }

  const ip = request.ip ?? '127.0.0.1'
  const { success, limit, reset, remaining } = await ratelimit.limit(ip)

  if (!success) {
    return NextResponse.json(
      { error: 'Too many requests' },
      {
        status: 429,
        headers: {
          'X-RateLimit-Limit': limit.toString(),
          'X-RateLimit-Remaining': remaining.toString(),
          'X-RateLimit-Reset': reset.toString(),
        },
      }
    )
  }

  return NextResponse.next()
}

Modificação de Headers de Resposta

O middleware pode modificar headers de resposta para políticas de segurança, cache e headers personalizados. Isso ocorre após o processamento da rota, mas antes de enviar a resposta ao cliente.

middleware.tstypescript
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const response = NextResponse.next()

  // Headers de segurança
  response.headers.set('X-Frame-Options', 'DENY')
  response.headers.set('X-Content-Type-Options', 'nosniff')
  response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
  response.headers.set(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self' 'unsafe-inline'"
  )

  // Headers personalizados para debugging
  response.headers.set('X-Middleware-Timestamp', Date.now().toString())

  return response
}

Tratamento de Erros no Middleware

O middleware deve tratar erros de forma elegante para evitar bloquear requisições. Erros não capturados no middleware resultam em uma resposta 500, o que pode bloquear o acesso a toda a aplicação.

middleware.tstypescript
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
  try {
    // Operações do middleware que podem falhar
    const token = request.cookies.get('session')?.value
    
    if (token) {
      const isValid = await validateSession(token)
      if (!isValid) {
        return NextResponse.redirect(new URL('/login', request.url))
      }
    }

    return NextResponse.next()
  } catch (error) {
    // Registra o erro mas não bloqueia a requisição
    console.error('Middleware error:', error)
    
    // Opções: continuar, redirecionar para erro, ou retornar resposta de erro
    return NextResponse.next()
  }
}

async function validateSession(token: string): Promise<boolean> {
  // Lógica de validação
  return true
}

Pronto para mandar bem nas entrevistas de React / Next.js?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Perguntas de Entrevista: Middleware do Next.js

As perguntas de entrevista sobre middleware avaliam a compreensão do seu modelo de execução, limitações e casos de uso apropriados.

Pergunta: Qual é a diferença entre middleware e API Routes para autenticação?

O middleware executa antes dos handlers de rota e pode interceptar requisições para qualquer rota, incluindo páginas estáticas e assets. API Routes executam apenas para requisições a /api/*. O middleware é ideal para verificações de autenticação em toda a aplicação, enquanto API Routes lidam com lógica de negócios específica.

Pergunta: Por que não é possível usar APIs do Node.js no middleware?

O middleware executa no Edge Runtime, que utiliza isolates V8 em vez de um ambiente Node.js completo. Isso permite cold starts inferiores a um milissegundo e distribuição global, mas limita as APIs disponíveis aos padrões Web (fetch, crypto, etc.).

Pergunta: Como passar dados do middleware para Server Components?

Definindo headers personalizados na requisição usando NextResponse.next({ request: { headers: modifiedHeaders } }). Server Components podem então ler esses headers usando a função headers() de next/headers.

Pergunta: Qual é a abordagem correta para gerenciamento de sessão no middleware?

Ler cookies de sessão e validar tokens usando bibliotecas compatíveis com Edge como jose para JWT. Não realizar consultas ao banco de dados diretamente no middleware; em vez disso, usar validação de tokens ou APIs de sessão externas.

Pergunta: Como implementar uma cadeia de middlewares no Next.js?

O Next.js suporta apenas um único arquivo de middleware, mas é possível encadear múltiplas funções compondo-as:

middleware.tstypescript
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

type MiddlewareFunction = (
  request: NextRequest
) => Promise<NextResponse | null>

const withAuth: MiddlewareFunction = async (request) => {
  const token = request.cookies.get('session')?.value
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }
  return null
}

const withLogging: MiddlewareFunction = async (request) => {
  console.log(`${request.method} ${request.nextUrl.pathname}`)
  return null
}

const middlewares = [withLogging, withAuth]

export async function middleware(request: NextRequest) {
  for (const mw of middlewares) {
    const result = await mw(request)
    if (result) return result
  }
  return NextResponse.next()
}

Melhores Práticas para Middleware em Produção

Minimizar o trabalho realizado no middleware melhora os tempos de resposta. Cada milissegundo no middleware atrasa a renderização da página. Evitar chamadas a APIs externas a menos que seja absolutamente necessário.

Usar o matcher apropriadamente reduz execuções desnecessárias do middleware. Excluir arquivos estáticos, imagens e rotas de API que não requerem processamento de middleware.

typescript
export const config = {
  matcher: [
    // Corresponde a todos os caminhos exceto arquivos estáticos
    '/((?!_next/static|_next/image|favicon.ico|public/).*)',
    // Ou lista explícita de rotas
    '/dashboard/:path*',
    '/api/protected/:path*',
  ],
}

Logs no middleware devem ser mínimos em produção. Cada console.log adiciona latência e consome recursos.

Conclusão

O middleware do Next.js 16 fornece uma poderosa capacidade de interceptação de requisições que executa no edge com latência mínima. Compreender suas restrições (Edge Runtime, sem APIs do Node.js) e seus casos de uso apropriados (autenticação, i18n, rate limiting) é essencial para construir aplicações de alto desempenho. Candidatos devem ser capazes de explicar a diferença entre middleware e API Routes, demonstrar tratamento de erros apropriado e compreender como passar dados para Server Components.

Desafio do dia

Você saberia encontrar o bug em React / Next.js?

Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Anthony Fillion-Maillet

Escrito por

Anthony Fillion-Maillet

Fundador da SharpSkill

Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.

Atualizado em 20 de setembro de 2026

Tags

#nextjs
#middleware
#edge-runtime
#autenticacao
#react

Compartilhar

Artigos relacionados