Criando uma Pokédex com Next.js - Parte 1
22 de setembro de 2022Esse post é a parte 1 de 3 de posts ensinando a criar um projeto com Next.js e hospedando ele na Vercel
Fala pessoal! Como vocês estão? Como prometido, nesse post vou falar sobre como criar um projeto usando o framework front-end Next.js. Por ser um conteúdo um pouco extenso, vou dividir esse post em duas partes de desenvolvimento e uma terceira parte de como hospedar esse projeto na Vercel. Em breve eu posto a segunda parte.
O que é o Next.js?
Next.js é um framework para desenvolvimento frontent que usa como base o React. O que isso quer dizer? O React é uma biblioteca JavaScript criado pelo time do Facebook para a construção de interfaces modernas, e o Next.js é considerado um framework, pois adiciona diversas funcionalidades em cima do React. Você pode acessar a documentação oficial do Next.js clicando aqui.
Algumas funcionalidades do Next.js
- Renderização estática pelo lado do servidor (server-side-rendering ou SSR);
- Suporte ao Typescript
- Tratamento de rotas automático
- Fast refresh
Muitas funcionalidades serão mais perceptíveis quando nossa aplicação estiver em ambiente produtivo, pois o Next.js tem dois pontos que são mais relevantes. O primeiro é tornar nossa aplicação React mais performática já que ele fornece diversas funcionalidades que se fossemos usar o React puro, precisariamos instalar bibliotecas por fora e a outra é a indexação do nosso site através dos motores de busca.
Falando um pouco sobre a indexacão, quando usamos o React por padrão, toda nossa interface é montada pelo lado do cliente (browser). Então quando algum motor de busca, ou crawler, tenta indexar uma página feita com React, ele não espera que nossa aplicação faça o carregamentos do arquivos da página. Ou seja, essa busca não retorna nada ou sem as informações relevantes para que nossa aplicação seja indexada.
Para isso, o Next.js atua usando um servidor Node.js para gerar essa página estática, proporcionando assim, a entrega da página pronta para o browser, ou seja, todo o HTML, CSS e JS. Esse comportamento se chama server-side-rendering.
Com essa funcionalidade, a página é retornada para o usuário toda montada. Pensando que esse usuário seja um motor de busca, todo o conteúdo da página retorna, facilitando assim a indexação.
Falando um pouco também sobre o roteamento, o Next.js se encarrega de fazer todo o tratamento de rotas automaticamente, então o que precisamos fazer é criar um arquivo com o nome da rota que queremos definir. Por exemplo, se queremos uma rota /blog
, então basta criar um arquivo chamado blog.js
. Se quisermos acessar um post do blog, exemplo /blog/meu-primeiro-post
, então criamos um diretório chamado blog
e dentro criamos um arquivo chamado [post].js
. Note que o nome post
está entre colchetes ([]
), fazendo com que o sistema de roteamento do Next.js entenda como algo parâmetro dinâmico, já que ele muda de post para post. No final a estrutura deve ser essa:
└── pages
└── blog.js
// ou
└── pages
└── blog
├── index.js
└── [post].js
O que vamos construir?
Nós vamos construir uma Pokédex. Para isso vamos usar uma API muito legal chamada PokéAPI, ela é gratuita e você pode explorar a documentação oficial dela aqui. Nessa primeira parte, vamos desenvolver apenas o layout da tela inicial, e na segunda parte vamos dinamizar o conteúdo através do consumo da API de Pokémons. Pra isso vamos usar o template básico gerado pelo CLI (command-line interface ou interface de linha de comando) do próprio Next.js.
Pré-requisitos
Não é necessário ser um especialista, mas é bom que você tenha ao menos um pouco de experiência com as tecnologias abaixo:
- HTML
- CSS
- JavaScript
- React
Além disso, verifique se você já tem o Node.js e o NPM instalados no seu computador. Para isso você pode rodar o seguinte comando no terminal:
node -v && npm -v
Se tudo der certo, você deverá ter uma saída parecida com essa:
v16.15.1 // Node.js
8.11.0 // npm
Obs.: A versão mínima do Node.js para usar o Next.js é a 12.22.0.
Caso você não tenha instalado no seu computador, é só baixar do site oficial e seguir o passo-a-passo de instalação.
Iniciando o projeto
Agora que já entendemos um pouco da tecnologia que vamos usar e do que vamos construir, podemos startar o projeto. Para isso, abra o terminal e navegue até o diretório que você deseja trabalhar e digite o seguinte comando (esse processo pode demorar um pouco):
npx create-next-app pokedex-nextjs
Rodando esse comando, você estará criando um projeto dentro do diretório que você estava, como citado no passo anterior, e você pode navegar até ele com o comando cd pokedex-nextjs
.
Entendendo a estrutura
Antes de começarmos a desenvolver, vamos entender um pouco da estrutura gerada.
├── pages
│ └── api
├── public
├── styles
├── next.config.js
├── package.json
├── package-lock.json
└── README.md
- pages: diretório onde ficam os arquivos de cada página que também funcionam como roteamento da aplicação;
- api: uma api disponibilizada através do sistema de roteamento automático do Next.js;
- public: diretório onde ficam os arquivos públicos da aplicação como imagens, ícones, etc;
- styles: diretório onde ficam arquivos de estilização como css, scss, less, etc;
- next.config.js: arquivo de configuração do Next.js da aplicação;
- package.json: arquivo de configuração do Node.js, onde ficam os scripts, as dependências e demais informações de inicialização da aplicação JavaScript;
- package-lock.json: arquivo de configuração onde ficam salvas as informações de versão, integridade e demais meta-dados das dependências da aplicação.
Desenvolvendo a tela inicial
Agora que já temos nossa estrutura pronta, vamos acessar o index.js
, dentro do diretório pages
e remover todo o código que vem por padrão e substituir pelo seguinte:
import { useState } from "react";
import Head from "next/head";
import Image from "next/image";
import styles from "../styles/Home.module.css";
export default function Home() {
const [pokemons, setPokemons] = useState([
{
name: "bulbasaur",
id: 1,
image:
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png",
elementTypes: ["grass", "poison"],
},
{
name: "ivysaur",
id: 2,
image:
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/2.png",
elementTypes: ["grass", "poison"],
},
{
name: "venusaur",
id: 3,
image:
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/3.png",
elementTypes: ["grass", "poison"],
},
]);
return (
<div className={styles.container}>
<Head>
<title>Pokédex</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className={styles.container}>
<h1 className={styles.title}>Pokédex</h1>
<div className={styles.pokedex}>
{pokemons.map(({ name, id, image, elementTypes }) => (
<a
href={`pokemon/${name}`}
key={id}
className={`${styles.card} ${styles[elementTypes[0]]}`}
>
<Image
className={styles["card-image"]}
alt={name}
src={image}
width={150}
height={150}
/>
<h2 className={styles["card-title"]}>
{id}. {name}
</h2>
<p className={styles["card-subtitle"]}>
{elementTypes.join(" | ")}
</p>
</a>
))}
</div>
</div>
</div>
);
}
Com o básico do layout da tela inicial pronto, agora vamos mexer um pouco na estilização dos componentes em dois arquivos de css, ambos dentro do diretório styles
. O primeiro deles é o globals.css
, você deve remover todo o código que vem por padrão e substituir pelo seguinte:
@import url("https://fonts.googleapis.com/css2?family=Rubik&display=swap");
html,
body {
background: #efefbb;
background: linear-gradient(to right, rgb(197, 230, 236), rgb(239, 187, 230));
color: #212121;
margin: 0;
font-family: rubik, san-serif;
overflow-x: hidden;
}
Esse primeiro arquivo, vai estilizar um pouco a base da aplicação como cor de fundo, cor da letra, também vamos adicionar uma nova fonte. No segundo arquivo, o Home.module.css
, você deve remover todo o código que vem por padrão e substituir pelo seguinte:
.container {
padding: 2.5rem;
margin: 0 auto;
}
.title {
text-align: center;
font-size: 3rem;
}
.pokedex {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
grid-gap: 1rem;
padding-inline-start: 0;
}
.card {
list-style: none;
padding: 2rem;
text-align: center;
border-radius: 0.25rem;
position: relative;
transition: 0.2s;
text-decoration: none;
color: #212121;
}
.card:hover {
box-shadow: 0 0 1rem 0.25rem rgba(0, 0, 0, 0.3);
}
.card-title {
margin-bottom: 0;
font-size: 2rem;
font-weight: normal;
position: relative;
z-index: 2;
}
.card-subtitle {
margin-top: 0.5rem;
color: #666;
position: relative;
z-index: 2;
}
.card-image {
background-color: #fff;
padding: 1rem;
border-radius: 0.25rem;
}
.steel {
background-color: #f4f4f4;
}
.fire {
background-color: #fddfdf;
}
.grass {
background-color: #defde0;
}
.electric {
background-color: #fcf7de;
}
.water,
.ice {
background-color: #def3fd;
}
.ground {
background-color: #f4e7da;
}
.rock {
background-color: #d5d5d4;
}
.fairy {
background-color: #fceaff;
}
.poison {
background-color: #98d7a5;
}
.bug {
background-color: #f8d5a3;
}
.dragon {
background-color: #97b3e6;
}
.psychic {
background-color: #eaeda1;
}
.flying {
background-color: #f5f5f5;
}
.fighting {
background-color: #e6e0d4;
}
.normal {
background-color: #f5f5f5;
}
Antes de testarmos o nosso site no navegador, precisamos adicionar uma configuração no arquivo next.config.js
. Essa configuração serve para podermos usar as imagens dos Pokémons que vem de um serviço externo, pois, por padrão o elemento de imagens do Next.js, <Image />
, usa como base o diretório public
para imagens, então devemos adicionar a seguinte configuração:
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
domains: ["raw.githubusercontent.com"],
},
};
module.exports = nextConfig;
Dessa forma, podemos usar tranquilamente as imagens externas que não teremos problema. Bora rodar o projeto.
Testando no navegador
Para ver o resultado do que desenvolvemos até agora, vamos executar o seguinte comando no terminal: npm run dev
. Se tudo ocorrer bem, uma mensagem parecida com essa deve aparecer:
> pokedex-nextjs@0.1.0 dev
> next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info - SWC minify release candidate enabled. https://nextjs.link/swcmin
event - compiled client and server successfully in 400 ms (178 modules)
wait - compiling...
event - compiled client and server successfully in 72 ms (178 modules)
Se você abrir o navegador no endereço http://localhost:3000
, deverá ver a seguinte tela:
Conclusão
Bom, nesse primeiro post aprendemos um pouco sobre o que é o Next.js e um pouco das suas incríveis funcionalidades que salvam as vida do desenvolvedor e tornam a experiência de desenvolvimento muito prazerosa. E claro, se você teve algum problema ou ficou com alguma dúvida, não esqueça de me mandar uma email, pra que eu possa te ajudar. 🙃
No próximo post, vamos usar a PokéAPI para mostrar os Pokémons de forma dinâmica e usar o roteamento para navegarmos para a tela de detalhes do Pokémon. Até mais 👋.