Tutorial Next.js para Iniciantes - Parte 2

Web

Tutorial Next.js para Iniciantes - Parte 2

Luiz Duarte
Escrito por Luiz Duarte em 21/12/2023
Junte-se a mais de 34 mil devs

Entre para minha lista e receba conteúdos exclusivos e com prioridade

Recentemente eu escrevi a primeira parte de uma nova série de tutoriais aqui no blog envolvendo Next.js, que você confere aqui. Uma das coisas mais legais do Next.js na minha opinião, além é claro da característica principal que é o SSR (Server-Side Rendering, as páginas são renderizadas no servidor), é o fato de terem incorporado no framework um roteamento nativo, o que torna muito mais simples e mais fácil de criar as rotas da sua aplicação de frontend, sem precisar do React Router DOM e tantas configurações quanto o ReactJS comum exigia.

Vimos um pouco disso na primeira parte, quando criamos uma página de about acessível através de uma rota /about. E é justamente isso que vamos aprofundar nessa segunda etapa da nossa série: como funcionam rotas em Next.js.

Parto do pressuposto aqui que você já fez a primeira parte desta série e que já tem um projeto Next.js criado na sua máquina, ok?

Vamos lá!

Livro Node.js

#1 – Rotas Aninhadas

Nós vimos na primeira parte que ao criarmos uma nova pasta dentro de app, automaticamente o Next.js cria uma rota de mesmo nome, certo? Mas e se precisarmos de subníveis? Aí entram as rotas aninhadas ou nested routes.

Uma nested route é quando você tem mais de um nível na hierarquia do seu site ou aplicação. Por exemplo, você tem uma loja online e nela tem uma seção de eletrônicos e outra de vestuário. Fácil de de implementar, certo? Abaixo sugestão:

  • /app
    • /eletronicos/page.js
    • /vestuario/page.js

Mas e se dentro de vestuário quisermos separar em duas subseções: masculino e feminino?

Neste caso podemos seguir o mesmo raciocínio para criar rotas baseado em pastas: criamos subpastas para os subníveis.

  • /app
    • /eletronicos/page.js
    • /vestuario/masculino/page.js
    • /vestuario/feminino/page.js

Implemente a lógica acima com um conteúdo simples nas páginas, apenas para entender como o roteamento funciona. Abaixo sugestão de conteúdo (masculino, mas pode adaptar para feminino também):

Agora coloque o projeto para rodar novamente e experimente acessar no browser as URLs de http://localhost:3000/vestuario/masculino e http://localhost:3000/vestuario/feminino para ver que elas funcionam lindamente, como abaixo.

Bacana não?

Curso Node.js e MongoDB

#2 – Rotas Dinâmicas

O exemplo anterior que eu dei é muito útil para criar a hierarquia “fixa” de páginas e subpáginas do seu site/aplicação web, quando já sabemos as páginas que existirão e/ou é uma quantidade finita, que vale a pena criar todas elas com antecedência. Mas e se nossa rota tiver um elemento dinâmico, como um id ou categoria que com base nesse parâmetro a página deva se renderizar com conteúdo diferente?

Este conceito se chama Rota Dinâmica ou Dynamic Route e é muito interessante a forma como o Next.js deixa isso preparado pra gente. Quando você quer criar uma rota onde parte dela é uma variável, crie uma pasta no nível do path usando o padrão pagina/[variavel]/page.js. Por exemplo, se você quer criar uma página de detalhes do produto, onde o id do produto virá na URL, pode criar a estrutura abaixo:

  • /app/
  • /produtos/[id]/page.js

Assim, você poderá acessar http://locahost:3000/produtos/1, http://localhost:3000/produtos/2 e assim por diante, sem precisar criar todas essas páginas de produto individualmente. Experimente fazer isso antes de avançar.

O próximo passo óbvio é você conseguir ter acesso a esse id no interior da página, certo? Isso porque para carregar dados personalizados com base no id do produto, você precisará saber qual o id está na URL. Abaixo um exemplo de código que captura e usa a informação do id:

Aqui valem algumas explicações. Primeiro, a diretiva “use client” no topo da página é necessária em todas páginas que precisam pegar informações do browser ou interagir com ele de qualquer forma, ou seja, sempre que o JS deva rodar no client-side. Segundo, o import do hook useParams é necessário para que consigamos pegar parâmetros de URL, sendo que estes parâmetros tem de ter sido definidos pela convenção de criar pasta com o nome [parâmetro] (entre colchetes). E terceiro, usamos o hook para carregar os parâmetros e com eles temos acesso ao mesmo, que no exemplo acima apenas renderizei na página, para ver a diferença entre os diferentes acessos, como abaixo.

Demais, não?

Curso FullStack

#3 – Pré-Rendering

Nas etapas anteriores nós nos focamos em aspectos de roteamento do Next.js pois para mim, quando vim do React “puro” foi um dos ganhos mais interessantes. Mas definitivamente Next.js não é sobre roteamento, mas sobre renderização, sendo o Pre-Rendering o elemento mais fundamental e inovador trazido pelo Next.js para o ecossistema React.

Mas afinal, o que é o Pre-Rendering?

No início do desenvolvimento server-side nós tínhamos tecnologias como PHP e ASP. Essas tecnologias se diferenciavam muito da criação tradicional (estática) de websites pois permitiam que as páginas fossem processadas no servidor ANTES de serem enviadas para o navegador do cliente, permitindo inclusive o acesso ao sistema de arquivos e bancos de dados antes desse envio acontecer. Assim, tínhamos páginas realmente dinâmicas e a era das aplicações web surgiu.

Essa forma de geração de páginas HTML dinâmicas é o que chamamos de SSR ou Server-Side Rendering. Mas isso não é ainda o Pre-Rendering do Next, então segue o fio…

Com o passar do tempo, a lógica dos frontends modernos se tornou tão complexa e ao mesmo tempo foi se exigindo cada vez mais que os desenvolvedores frontend (algo que nem existia no passado, éramos todos webmasters) se preocupassem com uma boa experiência do usuário que surgiram bibliotecas como ReactJS, justamente para permitir trabalhar com todos estes requisitos de maneira profissional, surgindo nessa época o conceito de SPA ou Single Page Application. Em uma SPA nós temos apenas um index.html e um arquivo JS, chamado de bundle, com toda a lógica de frontend dentro. Claro que o programador não escreve tudo dentro dele, mas na hora do build, é isso que vira.

Esse bundle JS é transmitido para o navegador do usuário (client-side) no primeiro acesso e conforme as requisições vão sendo feitas e funções JS vão sendo executadas, ele vai executando JS para gerar o código HTML e assim renderizar a página para o usuário, em tempo real. Para o servidor, zero stress, apenas entregar o bundle, mas para o browser, um alto processamento é necessário, o que na maioria dos casos não é um problema. Na maioria.

Em ao menos duas situações esse Post-Render ou CSR (Client-Side Render) é um problema: quando a aplicação é muito grande/pesada (às vezes por ser mal desenvolvida) ou quando você precisa de SEO (Search Engine Optimization). Nesses casos, pré-renderizar a aplicação, ou seja, pré-processar as páginas no servidor e já enviar elas para o browser prontas (como nos antigos PHP e ASP) ou pré-prontas (outra opção mais moderna, oferecida pelo Next.js), é a solução.

Independente do motivo, pré-rendering é justamente isso que acabei de explicar. Por padrão, todas as páginas escritas com Next.js são pré-renderizadas, o máximo possível, a menos que você use a diretiva “use client” no topo da página. Neste caso ela será renderizada da maneira React tradicional, no client-side via bundle. E tem vezes em que você vai precisar que seja assim mesmo, não é “errado” fazer isso.

Da mesma forma, também não entenda as páginas pré-renderizadas como páginas “estáticas”. Elas podem ter JS client-side normalmente porque logo após a renderização do HTML acontece um processo chamado hydration (hidratração) onde o JS client-side é injetado e funciona conforme programador.

Para complicar um pouco, existem dois tipos de pré-Render: Static Generation e Server-Side Rendering (embora ambos ocorram no server side, hehe).

Curso Beholder
Curso Beholder

#4 – Static Generation

A primeira forma de pré-render é a chamada Static Generation ou Geração Estática. Resumidamente, nela temos todas as páginas da sua aplicação NextJS sendo pré-renderizadas até o nível de HTML+CSS+JS diretamente no servidor durante a etapa de build (compilação), antes mesmo da aplicação ter seu deploy feito no servidor. Ou seja, se você tem uma página de about ou a própria home-page, ela terá seu HTML+CSS+JS gerado e 100% pronto para entrega ao usuário antes mesmo dele ser necessário pela primeira vez, entregando o máximo de performance e experiência para seu usuário, sem download de bundles enormes ou toneladas de JS processando para montar o HTML da página, mesmo em grandes e complexas aplicações. Além disso, como sua página será essencialmente HTML, qualquer robô de busca vai conseguir acessar e entender ela (SEO, lembra?).

Mas Luiz, quer dizer que Static Generation não permite dados dinâmicos? Somente para páginas estáticas mesmo?

Mais ou menos. Static Generation suporta sim dados dinâmicos, desde que esses dados não mudem. Ou seja, você pode carregar dados da página oriundos do seu banco de dados por exemplo. Aí durante o build esse carregamento dos dados vai acontecer e as página serão geradas, mas a partir daí, nenhum novo carregamento vai acontecer, baseado no uso dos visitantes do site, entende? Falaremos sobre páginas realmente dinâmicas mais tarde, mas por ora vamos entender como usar o Static Generation pois ele é a forma mais básica de pre-render e a que tem a melhor performance.

Nos exemplos anteriores nós fizemos páginas bem simples, todas, com exceção daquela que usamos a diretiva “use client” foram completamente geradas usando Static Generation, então quero propor um exemplo um pouco mais complexo. Como não temos banco de dados à disposição em nosso projeto de exemplo, vamos usar a API da PokeDex para Pokemons, disponível neste link (acesse para ver os dados que traz).

Assim, construa uma página no seu projeto chamada /app/pokemons/page.js e nela coloque o seguinte conteúdo:

Aqui eu criei uma função getData que usa a Fetch API para acessar a API de Pokemons e transforma o resultado em JSON (um processo que chamamos de serialização). Essa getData depois é chamada internamente na page function para pegarmos os results e renderizarmos uma lista de Pokemons na tela com ela.

O resultado, você vê abaixo.

Esses Pokemons que você vê listados foram obtidos através da API durante a etapa de build e incluídos no HTML pré-gerado pelo Next.js. Assim, todas as vezes que essa página for acessada, o mesmo HTML será entregue instantaneamente, sem qualquer nova requisição à API ou processamento seja realizado. Você pode inclusive experimentar desligar o JS do browser e acessar essa página, e verá que ela funciona normalmente.

E com isso finalizamos mais esta etapa de estudo do Next.js. Quer aprender a fazer deploy da sua aplicação? Leia este tutorial.

Olá, tudo bem?

O que você achou deste conteúdo? Conte nos comentários.

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *