📚 Módulo 06: Frontend - Setup Next.js, App Router e RSC
Bem-vindo à nova fronteira! Agora que nosso Backend NestJS está operante, construiremos a camada visual da TecLoja 04. Abandonaremos a arquitetura de Single Page Application (Vite) e adotaremos o framework React full-stack mais utilizado da atualidade: Next.js.
🚀 1. Inicializando o Projeto Next.js (Repositório 2)
O Next.js automatiza quase toda a complexidade do ecossistema React. Ele configura roteamento, Webpack, Babel e TypeScript instantaneamente.
No seu terminal, em uma pasta paralela ao backend, execute:
npx create-next-app@latest tecloja-frontend-next
Responda às perguntas interativas recomendadas pela comunidade corporativa:
- Use TypeScript? Yes
- Use ESLint? Yes
- Use Tailwind CSS? Yes
- Use
src/directory? Yes - Use App Router? Yes
- Customize default import alias? No
Entre na pasta (cd tecloja-frontend-next) e limpe o boilerplate do arquivo src/app/page.tsx para podermos começar do zero.
🧠 2. React Server Components (RSC) vs Client Components
A principal inovação do App Router (introduzido no Next 13+) é o paradigma de componentes.
🌐 Server Components (Padrão)
Por padrão, todos os arquivos do Next.js rodam no servidor Node.js. Eles nunca enviam JavaScript para o navegador do cliente, apenas HTML puro pré-renderizado.
- Vantagem: SEO impecável. Banco de dados pode ser acessado diretamente (Server Fetching). Zero KB adicionado ao bundle do cliente.
- Desvantagem: Não podem usar interatividade! Não podem usar
onClick,useStatenemuseEffect.
💻 Client Components ("use client")
Quando você precisa de interatividade (um botão que recalcula o carrinho, um input de formulário), você dita ao Next.js que aquele componente roda no cliente, adicionando a diretiva "use client" na primeira linha.
- Vantagem: Interatividade reativa clássica do React.
- Desvantagem: Maior bundle de JavaScript enviado ao navegador.
flowchart TD
A[Acesso à Rota /] --> B{O Componente tem interatividade?}
B -- Não (Catálogo de Imagens) --> C[React Server Component RSC]
B -- Sim (Botão Adicionar Carrinho) --> D[Client Component use client]
C --> E[HTML Rápido para SEO]
D --> F[JavaScript Baixado no Browser]
A arquitetura perfeita é construir Server Components injetando pequenos Client Components dentro deles (apenas nos botões ou partes reativas).
🎨 3. Estilização: TailwindCSS vs CSS Puro
Nos projetos anteriores (TecLoja 02 e 03) criamos layouts Glassmorphic usando arquivos styles.css puros e injetando as classes manualmente. Na TecLoja 04, usaremos TailwindCSS, o motor utilitário embutido por padrão no Next.js.
🥊 Comparativo
Exemplo: Um botão azul com sombra e hover
Abordagem Antiga (CSS Puro)
/* Você precisava alternar entre o arquivo CSS e o TSX constantemente */
.btn-primary {
background-color: #3b82f6;
color: white;
padding: 0.5rem 1rem;
border-radius: 0.25rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.btn-primary:hover {
background-color: #2563eb;
}
<button className="btn-primary">Comprar</button>
Abordagem Moderna (TailwindCSS)
/* Todo o design é declarado no próprio elemento via classes utilitárias atômicas */
<button className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded shadow-md transition-colors">
Comprar
</button>
Benefícios do Tailwind em E-commerces:
- Velocidade de Desenvolvimento: Não há “context-switching” (troca de tela) entre HTML e CSS. Você estiliza enquanto codifica a estrutura.
- Tamanho do Arquivo Mínimo: O Tailwind purge (remove) todas as classes que você não utilizou no build de produção. Seu CSS final terá pouquíssimos KBs.
- Consistência de Design System: As cores (
blue-500) e espaçamentos (p-4) são matemáticas estritas, impedindo aquele CSS caótico legado.
🖥️ 4. O Catálogo: Server Component Fetching
Vamos construir a nossa página principal da loja (O Catálogo). Como vitrines de e-commerce precisam de SEO, utilizaremos um Server Component.
Diferente do React padrão, no Next.js Server Components, a função do componente pode ser async e fazer a chamada para nossa API NestJS diretamente do lado do servidor, eliminando telas de Loading horríveis.
src/app/page.tsx
// Sem o 'use client', este arquivo roda no Node.js do servidor Vercel
import React from 'react';
import Link from 'next/link';
// Tipagem correspondente ao nosso DTO do NestJS
interface Produto {
id: number;
nome: string;
descricao: string;
preco: number;
estoque: number;
}
// O componente é ASSÍNCRONO!
export default async function CatalogoPage() {
// A requisição acontece no servidor do Next.js antes de enviar a página pro cliente
// O 'cache: no-store' garante que o Next.js não guarde a tela estática se o estoque mudar
const res = await fetch('http://localhost:3000/produtos', { cache: 'no-store' });
const produtos: Produto[] = await res.json();
return (
<div className="min-h-screen bg-slate-900 text-slate-100 font-sans p-8">
<header className="flex justify-between items-center mb-12 border-b border-slate-800 pb-4">
<h1 className="text-3xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-cyan-300">
🛒 TecLoja Enterprise
</h1>
<nav className="flex gap-4">
<Link href="/carrinho" className="text-slate-400 hover:text-white transition">Carrinho</Link>
<Link href="/admin" className="text-slate-400 hover:text-white transition">Admin</Link>
</nav>
</header>
<main className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-6">
{produtos.map((p) => (
// Efeito de Glassmorphism elegante construído com Tailwind
<div key={p.id} className="bg-slate-800/50 backdrop-blur-md border border-slate-700/50 rounded-xl p-6 shadow-xl hover:shadow-cyan-900/20 hover:-translate-y-1 transition-all duration-300">
<h2 className="text-xl font-semibold mb-2">{p.nome}</h2>
<p className="text-slate-400 text-sm mb-4 h-12 overflow-hidden">{p.descricao}</p>
<div className="flex justify-between items-center mb-4">
<span className="text-2xl font-bold text-cyan-400">R$ {p.preco}</span>
<span className={`text-xs px-2 py-1 rounded ${p.estoque > 0 ? 'bg-emerald-900/50 text-emerald-400' : 'bg-rose-900/50 text-rose-400'}`}>
{p.estoque > 0 ? `${p.estoque} uni.` : 'Esgotado'}
</span>
</div>
{/* Este botão precisa de interatividade. No Módulo 08, o transformaremos num Client Component! */}
<button disabled={p.estoque <= 0} className="w-full bg-blue-600 hover:bg-blue-500 disabled:bg-slate-700 text-white font-medium py-2 rounded-lg transition-colors">
Adicionar
</button>
</div>
))}
</main>
</div>
);
}
✅ Pré-Requisitos deste Módulo
Antes de passar para a configuração do BFF e cookies HttpOnly no Módulo 07, certifique-se de que:
- O backend NestJS do Módulo 05 está rodando localmente (com banco Postgres) para responder às chamadas de consulta.
- O ambiente de desenvolvimento local possui o Node.js (v18 ou superior) instalado.
🤔 Por que fizemos assim?
- Por que adotar o Next.js App Router com Server-Side Rendering (SSR) em vez de uma SPA clássica em React (com Vite)? Em SPAs clássicas, o navegador recebe um arquivo HTML em branco e o cliente fica encarregado de baixar arquivos JS pesados, executar o código e fazer requisições Ajax para popular a vitrine. Isso gera atrasos visuais (ruim para conexões 3G) e impossibilita a indexação de bots do Google, destruindo o SEO. O Next.js executa sob um servidor Node que pré-renderiza a página HTML completa com todos os produtos já inseridos no servidor e envia os dados montados para o browser, maximizando o SEO e a UX de carregamento.
- Por que utilizar React Server Components (RSC) assíncronos para o catálogo de produtos? RSC permite declarar a própria função do componente como
asynce efetuar ofetch()dos produtos da API diretamente no servidor. Isso elimina a necessidade de carregar bibliotecas de fetch no cliente, remove o JavaScript da requisição do bundle final do browser e dispensa o uso de hooks complexos de ciclo de vida (useState/useEffect) ou layouts de “loading” intermediários, reduzindo o processamento e uso de CPU no dispositivo do cliente. - Por que utilizar o TailwindCSS em vez de arquivos CSS puros para o design Glassmorphism? O Tailwind elimina a troca de contexto constante entre o arquivo TypeScript e folhas de estilo CSS, agilizando a codificação de estilos atômicos inline. Além disso, o motor de compilação do Tailwind varre o projeto e remove (purge) todas as classes CSS não utilizadas no build final, resultando em um bundle final ultraleve, com consistência rígida de espaçamentos e cores predefinidas.
🔍 Checkpoint
- Setup do Next.js: Verifique se as dependências do TailwindCSS e TypeScript foram configuradas com sucesso no arquivo
package.jsonno frontend. - Catálogo Renderizado: Execute o servidor local do frontend com
npm run dev, acessehttp://localhost:3000e certifique-se de que a vitrine de eletrônicos didáticos semeados no banco carrega instantaneamente. - RSC em Ação: Inspecione o código-fonte da página no navegador (Ctrl+U) e confirme se os produtos e preços do catálogo constam gravados diretamente no HTML enviado pelo servidor (comprovando a pré-renderização).
⚠️ Erros Comuns
| Erro | Causa | Solução |
|---|---|---|
Erro React hooks cannot be used in Server Components ao tentar renderizar a página |
O desenvolvedor tentou utilizar hooks de estado (useState) ou de ciclo de vida em um Server Component. |
Server Components rodam estritamente no servidor e não suportam interatividade. Adicione a diretiva "use client" como a primeiríssima linha do arquivo para transformá-lo em Client Component. |
| Alterações de preço ou estoque no banco de dados não aparecem no catálogo do Next.js | O Next.js armazena requisições HTTP em cache de build por padrão, agindo como Static Site Generation (SSG). | Adicione a opção { cache: 'no-store' } no segundo parâmetro da chamada de fetch() para forçar a renderização dinâmica (SSR) de dados a cada acesso. |
| O layout da página aparece desconfigurado e sem os estilos do TailwindCSS | O arquivo de configuração do Tailwind não está mapeando a pasta /app ou a pasta /src nas diretivas de leitura. |
Abra tailwind.config.ts e certifique-se de que a propriedade content inclui todas as pastas de componentes e páginas contendo classes do Tailwind. |
🏁 Conclusão
Sensacional! Com apenas um arquivo, nossa vitrine foi renderizada de forma ultrarrápida, já integrada à API NestJS do Módulo 03, e altamente otimizada para o GoogleBot! O uso do Tailwind entregou um layout “Glassmorphic” dark-mode deslumbrante sem a necessidade de um único arquivo .css auxiliar.
No Módulo 07, resolveremos a maior vulnerabilidade técnica do frontend: Autenticação. Criaremos um BFF (Backend For Frontend) via Next Route Handlers para ocultar nosso token JWT.