Next.js 15: Novidades e Guia de Migração Completo

January 15, 2025 (1y ago)

Fala dev! 👋

O Next.js 15 chegou com várias novidades incríveis que vão revolucionar a forma como desenvolvemos aplicações React. Neste artigo, vou te mostrar as principais mudanças e como migrar sua aplicação atual sem dor de cabeça.


🚀 Principais novidades do Next.js 15

1. Turbopack estável para desenvolvimento

Agora você pode usar o Turbopack (o bundler super rápido do Vercel) em produção:

# Ativação do Turbopack
next dev --turbo

Benefícios:

2. React 19 nativo

Suporte completo ao React 19 com todas as suas funcionalidades:

// Actions do React 19
async function createUser(formData: FormData) {
  'use server'
  
  const name = formData.get('name')
  // Lógica do servidor
}
 
// Componente com Action
export default function UserForm() {
  return (
    <form action={createUser}>
      <input name="name" required />
      <button type="submit">Criar usuário</button>
    </form>
  )
}

3. Partial Prerendering (PPR)

Renderização híbrida que combina estático e dinâmico:

// app/page.tsx
export default function HomePage() {
  return (
    <div>
      {/* Conteúdo estático */}
      <h1>Meu Blog</h1>
      
      {/* Conteúdo dinâmico com Suspense */}
      <Suspense fallback={<PostsSkeleton />}>
        <PostsList />
      </Suspense>
    </div>
  )
}

📦 Guia de migração passo a passo

Passo 1: Atualizar dependências

# Atualizar Next.js
npm install next@latest react@latest react-dom@latest
 
# Ou com pnpm
pnpm add next@latest react@latest react-dom@latest

Passo 2: Verificar breaking changes

# Comando para verificar incompatibilidades
npx @next/codemod@latest upgrade

Passo 3: Atualizar configurações

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Turbopack para desenvolvimento
  experimental: {
    turbo: {
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
  
  // PPR habilitado
  experimental: {
    ppr: true,
  },
}
 
module.exports = nextConfig

🛠️ Novas funcionalidades práticas

1. Server Actions melhoradas

// app/actions/user.ts
'use server'
 
import { revalidatePath } from 'next/cache'
import { redirect } from 'next/navigation'
 
export async function createUser(formData: FormData) {
  const name = formData.get('name') as string
  const email = formData.get('email') as string
  
  // Validação
  if (!name || !email) {
    throw new Error('Campos obrigatórios')
  }
  
  // Salvar no banco
  const user = await db.user.create({
    data: { name, email }
  })
  
  // Revalidar cache
  revalidatePath('/users')
  redirect(`/users/${user.id}`)
}

2. Caching inteligente

// app/posts/page.tsx
import { cache } from 'react'
 
// Cache automático por request
const getPosts = cache(async () => {
  const res = await fetch('https://api.example.com/posts', {
    next: { revalidate: 3600 } // 1 hora
  })
  return res.json()
})
 
export default async function PostsPage() {
  const posts = await getPosts()
  
  return (
    <div>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  )
}

3. Middleware otimizado

// middleware.ts
import { NextRequest, NextResponse } from 'next/server'
 
export function middleware(request: NextRequest) {
  // Verificação de autenticação
  const token = request.cookies.get('auth-token')
  
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }
  
  return NextResponse.next()
}
 
export const config = {
  matcher: ['/dashboard/:path*', '/api/protected/:path*']
}

⚡ Performance e otimizações

1. Bundle splitting automático

// Componentes são automaticamente code-split
import dynamic from 'next/dynamic'
 
// Lazy loading com fallback
const HeavyChart = dynamic(() => import('./HeavyChart'), {
  loading: () => <ChartSkeleton />,
  ssr: false
})
 
export default function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <HeavyChart />
    </div>
  )
}

2. Image optimization melhorada

import Image from 'next/image'
 
export default function ProductCard({ product }) {
  return (
    <div className="card">
      <Image
        src={product.image}
        alt={product.name}
        width={300}
        height={200}
        priority={product.featured} // Prioridade para imagens importantes
        placeholder="blur" // Blur enquanto carrega
        blurDataURL="data:image/jpeg;base64,..."
      />
    </div>
  )
}

🧪 Testes com Next.js 15

// __tests__/page.test.tsx
import { render, screen } from '@testing-library/react'
import HomePage from '@/app/page'
 
describe('HomePage', () => {
  it('deve renderizar o título principal', () => {
    render(<HomePage />)
    expect(screen.getByRole('heading', { level: 1 }))
      .toHaveTextContent('Bem-vindo')
  })
})
# Rodar testes
npm test
 
# Testes com watch mode
npm test -- --watch

🚀 Deploy e produção

Vercel (recomendado)

# Deploy automático
vercel --prod
 
# Preview de PRs
vercel --target preview

Docker

# Dockerfile otimizado para Next.js 15
FROM node:18-alpine AS base
 
# Dependencies
FROM base AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
 
# Build
FROM base AS builder
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build
 
# Production
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
 
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
 
EXPOSE 3000
CMD ["node", "server.js"]

✅ Checklist de migração


🎯 Conclusão

O Next.js 15 traz melhorias significativas em performance, developer experience e funcionalidades. A migração é relativamente simples, mas requer atenção aos breaking changes.

Principais benefícios:

Quer migrar? Comece pelo ambiente de desenvolvimento e vá testando gradualmente!

Até a próxima! 🚀

Allisson Lima
Desenvolvedor Frontend | Especialista em Next.js e React