Next.js
Resumo: Next.js é um framework baseado na biblioteca React usado na construção de aplicações web. Por ser uma biblioteca, React não fornece opinião sobre como você irá construir sua aplicação. Isso tem vantagens e desvantagens, uma vez que desenvolvedores podem se sentir perdidos sobre como começar a desenvolver uma aplicação com React. Next.js surge para resolver…
Next.js é um framework baseado na biblioteca React usado na construção de aplicações web.
Por ser uma biblioteca, React não fornece opinião sobre como você irá construir sua aplicação. Isso tem vantagens e desvantagens, uma vez que desenvolvedores podem se sentir perdidos sobre como começar a desenvolver uma aplicação com React.
Next.js surge para resolver esse problema especificando exatamente como uma aplicação React deve ser construída. Next.js diz como os arquivos devem ser organizados, como as rotas devem ser criadas, como o ambiente deve ser configurado e muito mais. Com Next.js você consegue criar aplicações React de maneira muito mais organizada!
Criando um aplicativo com Next.js
Para criar uma aplicação Next.js, você primeiro precisa ter o Node.js instalado.
No terminal, execute o comando:
npx create-next-app@latest projeto_nextjs --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"
Aguarde a instalação ser concluída:
Quando terminar, você verá a seguinte mensagem:
Agora, acesse o diretório criado e execute o comando de inicialização:
cd projeto_nextjs
npm run dev
Agora vá até o navegador e acesse:
http://localhost:3000
Pronto! Sua aplicação já está instalada.
Executando via Docker
Podemos ainda executar nossa aplicação usando Docker. Para isso, basta ter o Docker instalado. Crie um arquivo chamado “Dockerfile” na raiz do seu projeto Next.js e adicione o seguinte conteúdo:
FROM node:18
# cria um diretório para o app
WORKDIR /app
# copia o arquivo de configuração
COPY package*.json ./
# executa a instalação
RUN npm install
COPY . .
# define qual porta interna queremos acessar nosso site
ENV PORT=3000
# expõe ela para fora do container
EXPOSE 3000
# Executa a aplicação
CMD [ "npm", "run", "dev" ]
#docker build -t projeto-nextjs . # constroi a imagem
#docker ps # mostra o que está rodando em tempo real
#docker image ls # lista as imagens
#docker run -p 3000:3000 projeto-nextjs # executa o container
# EX.: 3000->porta da máquina real; 3000->porta aberta da VM
Para criar uma imagem docker, use o comando:
docker build -t projeto-nextjs .
Por fim, execute o container usando o comando:
docker run -p 3000:3000 projeto-nextjs
Estrutura de um projeto Next.js
Agora que já configuramos nossa primeira aplicação Next.js, dê uma olhada na estrutura principal do projeto:
Note que as pastas “.next” e “node_modules” estão cinza. Isso ocorre pois são pastas não sincronizadas pelo Git. Ou seja, quando transferimos nossa aplicação para o ambiente de produção, essas pastas deverão ser criadas antes do processo de inicialização (falaremos disso mais tarde).
Há três principais pastas:
- pages: onde ficam os arquivos com as páginas do website
- public: onde ficam os arquivos de acesso público
- styles: onde ficam armazenados os arquivos de folhas de estilo
O arquivo package.json contém as configurações de sua aplicação. Ele geralmente é alterado quando inserimos um comando via terminal (mas pode ser feito manualmente caso desejado). O arquivo README.md contém a documentação principal de sua aplicação.
Vamos começar a modificar nosso site, editando a página inicial do exemplo apresentado.
Editando a página inicial
Vamos editar a página inicial:
Abra o arquivo “/pages/index.js” e vamos modificá-lo. Que tal traduzirmos o conteúdo para português?
import Head from 'next/head';
import styles from '../styles/Home.module.css';
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Meu aplicativo Next</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1 className={styles.title}>
Bem-vindo ao <a href="https://nextjs.org">Next.js!</a>
</h1>
<p className={styles.description}>
Edite o arquivo <code>pages/index.js</code>
</p>
<div className={styles.grid}>
<a href="https://nextjs.org/docs" className={styles.card}>
<h3>Documentação →</h3>
<p>Encontre informações detalhadas sobre recursos e a API do Next.js.</p>
</a>
<a href="https://nextjs.org/learn" className={styles.card}>
<h3>Aprenda →</h3>
<p>Aprenda sobre o Next.js em um curso interativo com quizzes!</p>
</a>
<a
href="https://github.com/vercel/next.js/tree/master/examples"
className={styles.card}
>
<h3>Exemplos →</h3>
<p>Descubra e implemente projetos de exemplo com Next.js.</p>
</a>
<a
href="https://vercel.com/import?filter=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
>
<h3>Implante →</h3>
<p>
Implante agora seu site Next.js em uma URL pública com Vercel.
</p>
</a>
</div>
</main>
<footer>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Distribuído por{' '}
<img src="/vercel.svg" alt="Vercel" className={styles.logo} />
</a>
</footer>
<style jsx>{`
main {
padding: 5rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
footer {
width: 100%;
height: 100px;
border-top: 1px solid #eaeaea;
display: flex;
justify-content: center;
align-items: center;
}
footer img {
margin-left: 0.5rem;
}
footer a {
display: flex;
justify-content: center;
align-items: center;
text-decoration: none;
color: inherit;
}
code {
background: #fafafa;
border-radius: 5px;
padding: 0.75rem;
font-size: 1.1rem;
font-family: Menlo, Monaco, Lucida Console, Liberation Mono,
DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;
}
`}</style>
<style jsx global>{`
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue,
sans-serif;
}
* {
box-sizing: border-box;
}
`}</style>
</div>
)
}
Observe como a página imediatamente será recarregada:
Criando uma nova rota
Em Next.js, rotas vinculam URLs a determinados arquivos e pastas. Por exemplo, digamos que desejemos criar um site para uma livraria. Vamos criar uma rota para armazenar nossos livros.
No diretório /pages, crie um arquivo chamado “o-senhor-dos-aneis.js”. Adicione o seguinte conteúdo:
export default function OSenhorDosAneis() {
return <div>
<h1>Livro</h1>
<p><strong>Título:</strong> O Senhor dos Anéis</p>
<p><strong>Autor: </strong> J. R. R. Tolkien</p>
</div>;
}
Agora, pelo navegador, acesse o seguinte endereço:
http://localhost:3000/livro/o-senhor-dos-aneis
Criando links
Agora, vamos adicionar um link na página inicial para a rota recém-criada. Para incluirmos links, precisaremos importar essa funcionalidade da seguinte forma:
import Link from 'next/link';
Veja como ficará nosso arquivo
"index.js"
:
import Link from 'next/link';
import Head from 'next/head';
export default function Home() {
return (
<div>
<Head>
<title>Livraria</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1>Livros</h1>
<a href="/livro/o-senhor-dos-aneis">O Senhor dos Anéis</a>
</main>
<footer>
<p>Desenvolvido por <a href="https://diegomariano.com/" target="_blank">Diego Mariano</a></p>
</footer>
</div>
)
}
Observe que o link funciona corretamente:
Agora vamos adicionar um link para retornar para a página inicial no arquivo
/pages/livro/o-senhor-dos-aneis.js
:
import Link from 'next/link';
export default function OSenhorDosAneis() {
return <div>
<h1>Livro</h1>
<p><strong>Título:</strong> O Senhor dos Anéis</p>
<p><strong>Autor: </strong> J. R. R. Tolkien</p>
<Link href="/">Voltar para a página inicial</Link>
</div>;
}
Neste caso, o componente <Link> funciona de maneira similar a uma tag <a>.
Criando leiautes
Podemos incorporar um leiaute que poderá ser aplicado a todas as páginas usando componentes.
Para isso, crie uma pasta chamada components na raiz e adicione um arquivo chamado layout.js.
export default function Layout({ children }) {
return <div>{children}</div>;
}
Para usar um componente basta importá-lo com o comando import e depois declará-lo como se fosse uma tag, como por exemplo:
<Layout></Layout>
Vamos ver como funciona na prática. Importe esse componente na página o-senhor-dos-aneis.js:
import Link from 'next/link';
import Layout from '../../components/layout';
export default function OSenhorDosAneis() {
return <Layout>
<h1>Livro</h1>
<p><strong>Título:</strong> O Senhor dos Anéis</p>
<p><strong>Autor: </strong> J. R. R. Tolkien</p>
<Link href="/">Voltar para a página inicial</Link>
</Layout>;
}
Em seguida, vamos criar uma classe contêiner dentro de uma folha de estilos. Vamos usar um módulo CSS. No diretório components, crie um arquivo chamado layout.module.css:
.container {
max-width: 960px;
padding: 0 1rem;
margin: 3rem auto 6rem;
}
Agora, vamos importar essa folha de estilos dentro do layout:
import estilo from './layout.module.css';
export default function Layout({ children }) {
return <div className={estilo.container}>{children}</div>;
}
Veja o resultado:
Vamos fazer o mesmo na página inicial. Preste atenção no nível dos links:
import Link from 'next/link';
import Head from 'next/head';
import Layout from '../components/layout'
export default function Home() {
return (
<Layout>
<Head>
<title>Livraria</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1>Livros</h1>
<a href="/livro/o-senhor-dos-aneis">O Senhor dos Anéis</a>
</main>
<footer>
<p>Desenvolvido por <a href="https://diegomariano.com/" target="_blank">Diego Mariano</a></p>
</footer>
</Layout>
)
}
Estilos globais
Podemos ainda criar um estilo global que será aplicado a todas as páginas. Para isso, Next já possui um padrão: o arquivo pages/_app.js:
import '../styles/global.css';
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}
Agora, crie o arquivo styles/global.css:
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
line-height: 1.6;
font-size: 18px;
}
* {
box-sizing: border-box;
}
a {
color: #0070f3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
max-width: 100%;
display: block;
}
Note que não precisamos importar o arquivo _app.js, pois ele automaticamente aplica o estilo a todos os outros:
Agora que você aprendeu os conceitos básicos, vamos reformular toda nossa estrutura.
Criando um template padrão
Podemos criar um template padrão que se repete em todas as páginas usando o arquivo layout.js. Observe como queremos que nosso template fique ao final:
Note que há um cabeçalho e um rodapé coloridos de cinza. Adicionamos ainda um novo livro na nossa página inicial. Vamos começar pelo arquivo index.js:
import Link from 'next/link';
import Head from 'next/head';
import Layout, { titulo } from '../components/layout';
export default function Home() {
return (
<Layout>
<h1>Livros</h1>
<li><a href="/livro/o-senhor-dos-aneis">O Senhor dos Anéis</a></li>
<li><a href="/livro/harry-potter">Harry Potter</a></li>
</Layout>
)
}
Note que adicionamos o novo livro apontando para uma rota que ainda iremos criar. Não se preocupe com isso agora. O ponto mais importante desse arquivo é a linha, na qual importamos o layout e uma variávle chamada titulo. Vamos declará-la dentro do arquivo do layout. Para facilitar o processo de estilização, vamos utilizar o framework Bootstrap.
Bootstrap é um framework CSS e JavaScript que possui uma série de componentes que facilitam o desenvolvimento de aplicações web. Para importá-lo, basta acrescentar na tag <head> o link da CDN do CSS e no <footer> o link da CDN do arquivo com as funcionalidades JavaScript.
Vamos configurar o arquivo
layout.js
. Ele deverá fornecer a estrutura básica da página (preste atenção na variável
children
) e deverá permitir ainda que o título da página possa ser alterado. Observe como ficará o código:
import Head from 'next/head';
import Image from 'next/image';
import Link from 'next/link';
import estilo from './layout.module.css';
const nome = "Nome";
export const titulo = "Livros";
export default function Layout({ children }) {
return <>
<Head>
<title>{titulo}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet"></link>
</Head>
<header>
<nav className="navbar navbar-expand-md navbar-light bg-light">
<div className="container-fluid">
<a className="navbar-brand" href="/">Livros</a>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarCollapse">
<ul className="navbar-nav me-auto mb-2 mb-md-0">
{/* <li className="nav-item">
<a className="nav-link active" aria-current="page" href="/">Página inicial</a>
</li> */}
</ul>
</div>
</div>
</nav>
</header>
<main>
<div className="container py-5">
{children}
</div>
</main>
<footer className="footer py-3 mt-5 bg-body-tertiary small text-center">
<span className="text-body-secondary">{titulo} por <Link href="https://diegomariano.com" target='_blank'>Diego Mariano</Link>.</span>
{/* <!-- Scripts --> */}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"></script>
</footer>
</>;
}
Agora, sempre que quisermos carregar uma página com essa estrutura básica, basta chamar o componente <Layout>.
Todo o conteúdo será carregado dentro da tag <main></main>, onde declaramos a variável
children
.
Agora, para testar nosso código, vamos adicionar um novo livro. No diretório “livro”, crie o arquivo “harry-potter.js” e acrescente o seguinte conteúdo:
import Link from 'next/link';
import Head from 'next/head';
import Layout, {titulo} from '../../components/layout';
const subtitulo = " - Harry Potter";
export default function HarryPotter() {
return (
<Layout>
<Head>
<title>{titulo+subtitulo}</title>
</Head>
<h1>Livro</h1>
<p><strong>Título:</strong> Harry Potter</p>
<p><strong>Autor: </strong> J. K. Rowling</p>
<Link href="/">Voltar para a página inicial</Link>
</Layout>
);
}
Observe que criamos uma variável chamada subtitulo. Para alterarmos o título da página, criamos uma seção <Head> e adicionamos uma nova tag <title>. Essa tag irá substituir a tag padrão presente em layout.js.
Note que não precisamos passar mais nenhuma configuração de estilo para esse arquivo, pois ele irá importar tudo do arquivo layout.js. Observe como ficará nossa página:
Perceba que o cabeçalho e o rodapé foram importados do arquivo de layout. Logo, toda vez que quisermos criar uma nova página, basta importar dessa mesma forma.
Criando rotas dinâmicas
Para criar uma rota dinâmica, basta criar uma pasta com nome entre colchetes. Por exemplo: [id]
A seguir, vamos criar um arquivo chamado buscar.tsx dentro da pasta [id] e adicionar o seguinte conteúdo:
import { useRouter } from "next/router"
export default function buscar(){
const router = useRouter();
const id = router.query.id;
return (
<>buscar/{id}/</>
)
}
Note que podemos acessar essa página com a seguinte URL:
Podemos modificar o valor alterando a URL da chamada:
Note que podemos passar outras strings pela URL:
http://localhost:3000/rotas/1234/buscar?nome=teste
Neste caso, pomodes acessar isso chamando:
console.log(router.query)
Criando APIs
Vamos agora criar uma API com Next.js. No diretório “pages”, crie uma pasta chamada “api”. Crie um arquivo chamado pessoas.tsx.
export default function(req, res){
res.status(200).json([
{ nome: "José" },
{ nome: "Maria"}
])
}
Pelo navegador, você pode acessá-lo da seguinte forma:
Permitindo apenas o método POST
Podemos bloquear requisições do tipo GET usando o objeto req. Observe:
export default function(req, res){
const metodo = req.method;
if(metodo === "POST"){
res.status(200).json([
{ nome: "José" },
{ nome: "Maria"}
])
}
else if(metodo === "GET"){
res.status(405).send("Método permitido: POST.")
}
}
Podemos acessar os dados usando uma ferramenta de consumo de APIs como o Postman:
Consumindo APIs com Next.js
Crie uma pasta chamada pessoas e adicione um arquivo chamado index.tsx. Para consumirmos a API, precisaremos usar duas características do React: useEffect e useState.
Observe como ficaria o código:
import { useEffect, useState } from "react"
export default function pessoas(){
// lista todas as pessoas
const [pessoas, setPessoas] = useState(null);
useEffect(()=>{
fetch('http://localhost:3000/api/pessoas', {method: "post"})
.then(i => i.json())
.then(setPessoas)
}, [])
return (
<>
<h1>Pessoas</h1>
<ul>
{
pessoas?.map(
(pessoa, id) => <li key={id}>{pessoa.nome}</li>
)
}
</ul>
</>
)
}
Agora, você pode acessar seus dados pelo navegador em:
URL Original da postagem: Read More
Deixe uma resposta