Fundamentos do Next.js 15

0/26 aulas0%
teoria

Entendendo a Estrutura de Pastas e o App Router

Aprenda sobre entendendo a estrutura de pastas e o app router

35 min
Aula 3 de 5

Módulo 1: Introdução e Setup do Next.js 15 - Aula: Entendendo a Estrutura de Pastas e o App Router

Olá e seja bem-vindo(a) à primeira aula teórica do nosso curso de Fundamentos do Next.js 15! 🎉

Nesta aula, vamos mergulhar no coração de como o Next.js 15 organiza suas aplicações: o App Router. Ele representa uma mudança fundamental em relação às versões anteriores (que usavam o Pages Router) e é essencial para construir aplicações modernas, performáticas e escaláveis com Next.js.

Compreender a estrutura de pastas e os arquivos especiais do App Router é o primeiro passo para dominar o desenvolvimento com Next.js 15. Vamos lá!


1. Introdução ao App Router ✨

O App Router, introduzido no Next.js 13 e agora o padrão no Next.js 15, é construído sobre os React Server Components. Ele oferece uma abordagem mais flexível e poderosa para o roteamento e a renderização, permitindo que você crie layouts aninhados, estados de carregamento instantâneos, tratamento de erros robusto e muito mais, tudo isso com um foco na performance.

A principal filosofia do App Router é que a estrutura de pastas dentro do diretório app define as rotas da sua aplicação. Cada pasta representa um segmento de URL, e arquivos especiais dentro dessas pastas definem a UI (User Interface) para essa rota.

Por que o App Router? 🤔

  • Server Components por padrão: Melhor performance, menor JavaScript enviado ao cliente.
  • Nested Layouts: Layouts complexos que podem ser aninhados e compartilhados entre rotas.
  • Streaming: Carrega partes da UI progressivamente, melhorando a percepção de performance.
  • Data Fetching simplificado: async/await diretamente nos componentes.
  • Ferramentas de UI de carregamento e erro: Estados de carregamento e tratamento de erros declarativos.

2. Entendendo a Estrutura de Pastas e Arquivos Especiais 📁

Dentro do diretório app, a estrutura de pastas é o mapa da sua aplicação. Vamos explorar os arquivos e convenções mais importantes.

app/
├── (auth)/
│   ├── login/
│   │   └── page.tsx
│   └── layout.tsx
├── dashboard/
│   ├── layout.tsx
│   ├── page.tsx
│   ├── settings/
│   │   └── page.tsx
│   ├── analytics/
│   │   └── page.tsx
│   └── loading.tsx
├── _components/
│   └── Button.tsx
├── api/
│   └── users/
│       └── route.ts
├── layout.tsx
├── page.tsx
├── global-error.tsx
└── not-found.tsx

2.1. Arquivos Essenciais para Rotas 🛣️

page.tsx (ou .js, .jsx)

  • Propósito: Define a interface de usuário única de uma rota e a torna publicamente acessível.
  • Localização: Deve estar dentro de uma pasta de rota.
  • Exemplo: app/dashboard/page.tsx corresponde à rota /dashboard. app/page.tsx é a rota raiz (/).
// app/dashboard/page.tsx
export default function DashboardPage() {
  return (
    <main>
      <h1>Bem-vindo ao Dashboard!</h1>
      <p>Este é o conteúdo principal da sua página.</p>
    </main>
  );
}

layout.tsx (ou .js, .jsx)

  • Propósito: Define a interface de usuário compartilhada para um segmento de rota e seus filhos. Um layout envolve os page.tsx e outros layout.tsx aninhados.
  • Localização: Pode estar em qualquer pasta de rota, incluindo a pasta app raiz.
  • Características:
    • Recebe uma prop children que será preenchida com os componentes de rota filhos (outros layouts ou páginas).
    • Não re-renderiza quando a navegação ocorre entre páginas que compartilham o mesmo layout.
    • É um Server Component por padrão.
    • O layout.tsx raiz (app/layout.tsx) é obrigatório e deve definir as tags <html> e <body>.
// app/layout.tsx (Layout Raiz)
import './globals.css'; // Importa estilos globais
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="pt-BR">
      <body>{children}</body>
    </html>
  );
}
// app/dashboard/layout.tsx (Layout Aninhado)
import Navbar from '../_components/Navbar'; // Exemplo de componente compartilhado
 
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <section>
      <Navbar /> {/* Componente de navegação para o dashboard */}
      <aside>
        <p>Menu Lateral do Dashboard</p>
        {/* ... links de navegação do dashboard */}
      </aside>
      <main>{children}</main> {/* Aqui será renderizado o page.tsx ou outros layouts aninhados */}
    </section>
  );
}

2.2. Arquivos para UI de Carregamento e Erro ⏳⚠️

loading.tsx (ou .js, .jsx)

  • Propósito: Exibe um estado de carregamento instantâneo enquanto o conteúdo de uma rota está sendo carregado.
  • Localização: Dentro de uma pasta de rota.
  • Características:
    • É automaticamente envolvido pelo layout.tsx pai.
    • Ajuda a melhorar a experiência do usuário, fornecendo feedback visual.
// app/dashboard/loading.tsx
export default function Loading() {
  return (
    <div className="loading-spinner">
      <h2>Carregando Dashboard...</h2>
      {/* Você pode adicionar um spinner ou qualquer UI de carregamento aqui */}
    </div>
  );
}

error.tsx (ou .js, .jsx)

  • Propósito: Cria um limite de erro para uma rota, capturando erros em seus filhos e exibindo uma UI de fallback.
  • Localização: Dentro de uma pasta de rota.
  • Características:
    • Recebe as props error (o objeto de erro) e reset (uma função para tentar renderizar o conteúdo novamente).
    • É um Client Component por padrão (precisa da diretiva 'use client').
// app/dashboard/error.tsx
'use client'; // Error components must be Client Components
 
import { useEffect } from 'react';
 
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    // Log the error to an error reporting service
    console.error(error);
  }, [error]);
 
  return (
    <div>
      <h2>Algo deu errado!</h2>
      <p>{error.message}</p>
      <button
        onClick={
          // Attempt to recover by trying to re-render the segment
          () => reset()
        }
      >
        Tentar novamente
      </button>
    </div>
  );
}

not-found.tsx (ou .js, .jsx)

  • Propósito: Exibe uma UI personalizada quando a rota não é encontrada.
  • Localização: Pode ser definida no nível da rota (app/dashboard/not-found.tsx) ou no nível raiz (app/not-found.tsx).
  • Características:
    • Substitui a página 404 padrão do Next.js.
    • Para acioná-lo, você pode usar a função notFound() do Next.js em um Server Component.
// app/not-found.tsx
import Link from 'next/link';
 
export default function NotFound() {
  return (
    <div>
      <h2>Página Não Encontrada</h2>
      <p>Não foi possível encontrar o recurso solicitado.</p>
      <Link href="/">Voltar para a Home</Link>
    </div>
  );
}

global-error.tsx (ou .js, .jsx)

  • Propósito: Um limite de erro global que captura erros em todos os layouts e páginas, incluindo o layout.tsx raiz.
  • Localização: Apenas na pasta app raiz.
  • Características:
    • Deve ser um Client Component ('use client').
    • Substitui o <html> e <body> do layout raiz quando um erro ocorre.
// app/global-error.tsx
'use client';
 
export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <html>
      <body>
        <h2>Algo deu muito errado globalmente!</h2>
        <p>{error.message}</p>
        <button onClick={() => reset()}>Tentar novamente</button>
      </body>
    </html>
  );
}

2.3. Outros Arquivos Especiais e Convenções 🧩

template.tsx (ou .js, .jsx)

  • Propósito: Semelhante a um layout.tsx, mas seus filhos re-renderizam em cada navegação.
  • Localização: Dentro de uma pasta de rota.
  • Características:
    • Útil para lógicas que dependem de estado por rota, como animações de entrada/saída.
    • Recebe a prop children.
// app/dashboard/template.tsx
import React from 'react';
 
export default function DashboardTemplate({ children }: { children: React.ReactNode }) {
  console.log('Template do Dashboard renderizado!');
  return (
    <div>
      {/* Este div será re-renderizado em cada navegação dentro do dashboard */}
      {children}
    </div>
  );
}

default.tsx (ou .js, .jsx)

  • Propósito: Fornece uma UI de fallback para Parallel Routes quando o slot de rota correspondente não está ativo.
  • Localização: Dentro de um slot de rota paralela (ex: app/@modal/default.tsx).
  • Características:
    • Não é tão comum para iniciantes, mas é poderoso para layouts complexos com múltiplos slots de conteúdo.

route.ts (ou .js, .jsx, .mjs)

  • Propósito: Cria um endpoint de API (uma rota de API) dentro do App Router.
  • Localização: Dentro de uma pasta de rota.
  • Características:
    • Permite definir manipuladores para métodos HTTP (GET, POST, PUT, DELETE, etc.).
    • Substitui o diretório pages/api do Pages Router.
// app/api/hello/route.ts
import { NextResponse } from 'next/server';
 
export async function GET(request: Request) {
  return NextResponse.json({ message: 'Olá do App Router API!' });
}
 
export async function POST(request: Request) {
  const data = await request.json();
  return NextResponse.json({ received: data, status: 'success' }, { status: 200 });
}

middleware.ts (ou .js)

  • Propósito: Permite executar código antes que uma requisição seja concluída, modificando a requisição ou resposta.
  • Localização: Na raiz do projeto (/middleware.ts) ou dentro de src/middleware.ts.
  • Características:
    • É executado no Edge Runtime (ambiente de execução global e de baixa latência).
    • Pode ser usado para autenticação, redirecionamentos, modificação de headers, etc.
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
 
export function middleware(request: NextRequest) {
  const currentUser = request.cookies.get('currentUser')?.value;
 
  if (currentUser && request.nextUrl.pathname.startsWith('/auth')) {
    return NextResponse.redirect(new URL('/dashboard', request.url));
  }
 
  if (!currentUser && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/auth/login', request.url));
  }
}
 
export const config = {
  matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
};

2.4. Convenções de Pastas 📦

(folder) - Route Groups (Grupos de Rotas)

  • Propósito: Organizar rotas em grupos lógicos sem afetar o caminho da URL.
  • Exemplo: app/(marketing)/about/page.tsx ainda será acessível em /about.
  • Características:
    • Útil para separar partes da aplicação com layouts diferentes (ex: (auth), (dashboard), (marketing)).
    • Permite que vários layouts raiz existam na mesma pasta app.
app/
├── (marketing)/
│   ├── layout.tsx  // Layout para rotas de marketing
│   └── about/
│       └── page.tsx // Rota: /about
├── (shop)/
│   ├── layout.tsx // Layout para rotas da loja
│   └── products/
│       └── page.tsx // Rota: /products
└── page.tsx // Rota: /

_folder - Pastas Privadas

  • Propósito: Pastas que não são rotas e não devem ser acessíveis publicamente.
  • Exemplo: app/_components, app/_lib, app/_utils.
  • Características:
    • Útil para armazenar componentes reutilizáveis, funções utilitárias, hooks, etc.
    • O Next.js ignora pastas que começam com _ ao criar rotas.
app/
├── dashboard/
│   └── page.tsx
├── _components/
│   └── Header.tsx
│   └── Footer.tsx
├── _utils/
│   └── helpers.ts
└── page.tsx

3. Server Components vs. Client Components 🔄

Um conceito fundamental no App Router é a distinção entre Server Components e Client Components.

  • Server Components (Padrão):

    • Renderizados no servidor.
    • Não podem usar hooks de React como useState, useEffect, ou useContext.
    • Não têm acesso ao DOM ou eventos do navegador.
    • Podem acessar diretamente o sistema de arquivos ou bancos de dados (APIs de servidor).
    • Não adicionam JavaScript ao bundle do cliente, resultando em carregamentos mais rápidos.
    • Podem ser async para data fetching.
  • Client Components:

    • Renderizados no cliente (no navegador).
    • Podem usar hooks de React, eventos do navegador e acessar o DOM.
    • São interativos.
    • Para definir um Client Component, adicione a diretiva 'use client' no topo do arquivo.
// app/dashboard/page.tsx (Server Component por padrão)
// Pode ser async para buscar dados
async function getPosts() {
  const res = await fetch('https://api.example.com/posts');
  return res.json();
}
 
export default async function DashboardPage() {
  const posts = await getPosts(); // Data fetching diretamente no Server Component
 
  return (
    <div>
      <h1>Meus Posts</h1>
      <ul>
        {posts.map((post: any) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
      {/* Um Client Component pode ser importado aqui */}
      <InteractiveButton />
    </div>
  );
}
// app/_components/InteractiveButton.tsx (Client Component)
'use client'; // <-- Esta diretiva o torna um Client Component
 
import { useState } from 'react';
 
export default function InteractiveButton() {
  const [count, setCount] = useState(0);
 
  return (
    <button onClick={() => setCount(count + 1)}>
      Você clicou {count} vezes!
    </button>
  );
}

4. Resumo e Próximos Passos 🚀

Nesta aula, exploramos a estrutura de pastas e os arquivos especiais que compõem o App Router do Next.js 15. Você aprendeu que:

  • O diretório app é a base do App Router.
  • Pastas definem segmentos de URL.
  • page.tsx torna uma rota acessível e define sua UI única.
  • layout.tsx define UI compartilhada e pode ser aninhado.
  • loading.tsx e error.tsx fornecem feedback visual e tratamento de erros.
  • not-found.tsx e global-error.tsx lidam com rotas não encontradas e erros globais.
  • route.ts cria endpoints de API.
  • middleware.ts intercepta requisições.
  • ( ) (Route Groups) e _ (Pastas Privadas) ajudam na organização.
  • A distinção entre Server Components (padrão) e Client Components ('use client') é crucial para a performance e interatividade.

Com essa base sólida, você está pronto para começar a construir suas primeiras rotas e componentes no Next.js 15. Na próxima aula, vamos colocar a mão na massa e configurar nosso ambiente de desenvolvimento para iniciar um novo projeto Next.js!

Próximos Passos:

  • Módulo 1 - Aula 2: Setup do Ambiente de Desenvolvimento e Criação do Primeiro Projeto Next.js 15.

Até lá! 👋

© 2025 Escola All Dev. Todos os direitos reservados.

Entendendo a Estrutura de Pastas e o App Router - Fundamentos do Next.js 15 | escola.all.dev.br