Next: um guia de como depurar aplicações web
O Next.js é um framework React poderoso que oferece diversos recursos para otimizar o desenvolvimento de aplicações web, incluindo renderização no servidor (SSR) e geração de sites estáticos (SSG).
No entanto, como em qualquer projeto de software, a depuração pode ser um desafio, especialmente quando se trata de aplicações complexas com múltiplos componentes e funcionalidades.
Neste artigo, vamos abordar as principais técnicas para depurar aplicações Next.js, tanto no lado do cliente quanto no lado do servidor, utilizando ferramentas como o VS Code, Chrome DevTools e o próprio Next.js.
Além disso, também vamos falar sobre dicas para otimizar o desempenho da sua aplicação e para lidar com logs de forma eficiente.
O que é depuração?
Para começar, depurar código é como encontrar o “dedo duro” no seu programa. Ou seja, é um processo para descobrir e corrigir erros que impedem o seu código de funcionar como esperado.
Imagine que você está construindo uma casa com instruções. Se você seguir as instruções passo a passo, mas se a casa não estiver do jeito que você queria, você precisa descobrir qual parte das instruções está errada e corrigir para que a casa fique perfeita.
É a mesma coisa com o código. Você escreve as instruções para o computador, mas se ele não fizer o que você espera, você precisa depurar o código para encontrar os erros e corrigi-los.
Existem ferramentas para te ajudar a depurar, como o "depurador" do seu editor de código ou mesmo o developer tools do navegador.
Ele permite que você execute o código linha por linha, veja o valor das variáveis e encontre os erros que estão causando problemas.
Como depurar do lado do cliente
O lado do cliente em uma aplicação Next.js é executado no navegador do usuário, utilizando Javascript.
As ferramentas de depuração padrão do navegador, como o Chrome DevTools(developer tools), podem ser utilizadas para identificar erros e problemas de performance.
Nesse sentido as principais ferramentas são:
Chrome DevTools
O Chrome DevTools oferece diversas ferramentas para depurar o lado do cliente de uma aplicação Next.js, que inclui:
- Debugger: Permite definir breakpoints, inspecionar variáveis e executar código passo a passo.
- Sources: Permite visualizar e editar o código Javascript da aplicação.
- Network: Permite monitorar o tráfego de rede da aplicação, incluindo requisições HTTP e respostas.
- Elements: Permite visualizar e editar o DOM da aplicação.
- Performance: Permite monitorar o desempenho da aplicação, incluindo tempo de carregamento, tempo de resposta e uso de memória.
Como colocar em prática?
Vamos partir de um projeto full stack. Ou seja, Front-end e Back-end.
Para começar, faça o download ou clone nesse link: code-connect-artigo.
Os pré requisitos são:
- Docker, recomendo o docker desktop
- VSCode
- Node: versão 18+
Depois, instale as dependências:
npm
ou
yarn
Uma vez instalado as dependências, execute o docker, abra o docker desktop primeiro.
Na raiz do projeto, execute o comando para subir o container docker:
docker compose up
Em seguida abra um novo terminal e execute as migrations
, responsável por popular a base de dados:
yarn build
Agora está tudo pronto para subir a aplicação, nesse link. Para fazer isso, é só rodar o comando:
yarn dev
Muito bem, agora você deve ver a página a seguir:
React Developer Tools
Para facilitar a depuração de componentes React, recomenda-se a instalação da extensão React Developer Tools para o navegador Google Chrome.
Esta ferramenta é extremamente benéfica para a análise dos componentes React. Com ela, você tem a capacidade de visualizar não apenas os componentes renderizados, mas também acessar e inspecionar suas propriedades e respectivos valores.
Isso facilita significativamente o processo de diagnóstico e otimização de componentes, proporcionando um entendimento mais profundo da estrutura e do comportamento de sua aplicação React.
Para utilizar a extensão após sua instalação e ativação no navegador, siga esses passos:
- Abra a página do Code Connect no seu navegador.
- Clique com o botão direito do mouse em qualquer área da página.
- Selecione a opção "Inspecionar" no menu, clicando com o botão do mouse.
- Então abrirá as ferramentas de desenvolvedor do navegador, permitindo que você analise e depure a página aberta.
A ferramenta React Developer Tools é realmente útil, especialmente quando você está começando em um novo projeto e ainda está se familiarizando com sua estrutura e código.
Afinal de contas, permite que você inspecione de maneira direta a estrutura da página e os componentes React, oferecendo uma visão clara de como tudo está organizado.
Isso pode ser extremamente valioso para acelerar o processo de compreensão e contribuição para o projeto.
Agora é sua vez de colocar em prática
Como uma pessoa desenvolvedora do projeto Code Connect, você recebeu a tarefa de corrigir um bug específico: o modal de comentários não está abrindo quando as pessoas clicam no ícone de comentar.
O objetivo é garantir que, ao realizar essa ação, o modal de comentários seja exibido corretamente.
Para solucionar esse problema, você precisará investigar a lógica de interação do ícone com o modal, revisando a implementação dos eventos de clique e a funcionalidade de abertura do modal no código.
É essencial verificar se os eventos estão sendo capturados corretamente e se a lógica que controla a visibilidade do modal está funcionando como esperado.
Abra o developer Tools, acesse o inspetor de componentes React. Clique na seta da mesma forma que eu fiz no primeiro gif e inspecione o ícone que representa visualmente o cometário:
Recapitulando:
- 1 - Posicione a seta em cima do ícone
- 2 - Está marcado qual é o componente
- 3 - O caminho de onde se encontra o componente
Agora, clique no ícone de copiar, logo ao lado direito de onde se encontra o caminho( o passo #3).
Após copiar o caminho, com o VSCode aberto, se você usa Windows, uma tecla de atalho para ir direto para o componente é apertar:
CTRL + P
, isso vai abrir a paleta de comandos do VSCode e então cole o caminho e aperte enter:
Imediatamente é aberto o arquivo e a linha que se encontra aquele componente. Isso é tão maravilhosamente produtivo que já não vivo sem esses atalhos.
export const ModalComment = ({ action }) => {
const modalRef = useRef(null);
return (
<>
<Modal ref={modalRef}>
<form action={action} onSubmit={() => modalRef.current.closeModal()}>
<Subheading>Deixe seu comentário sobre o post:</Subheading>
<Textarea
required
rows={8}
name="text"
placeholder="Digite aqui..."
/>
<div className={styles.footer}>
<SubmitButton>Comentar</SubmitButton>
</div>
</form>
</Modal>
<IconButton onClick={() => modalRef.current.showModal()}>
<Chat />
</IconButton>
</>
);
};
Perceba que na linha #31 o evento de clique executa modal.current.showModal( )
, e fazendo uma breve análise do código, podemos ver que o método showModal é uma referência do componente <Modal>
.
Volte para o React DevTools, e inspecione o componente ModalComment
, onde podemos ver os hooks, que retorna as referências, closeModal e openModal, então não é correto o evento de clique do comentário chamar o modalRef.current.showModal, pois nenhum showModal é retornado pelo Modal. Então basta, ajustarmos o evento de clique do IconButton
para o método correto:
<IconButton onClick={() => modalRef.current.openModal()}>
<Chat />
</IconButton>
O processo de debug completo você ver aqui:
Ao analisar via React DevTools foi rápido e eficiente para encontrar o erro, ao corrigir o evento de clique para executar o modalRef.current.openModal o modal passou a ser exibido corretamente.
Comemore! Bug resolvido!
Como depurar pelo DevTools via Tab Sources
Depurar através da tab sources não é necessário fazer nenhuma configuração extra, pois é nativo dos navegadores.
Então, por exemplo, podemos abrir o código no VSCode e no código adicionar um breakpoint, usando o método debugger
, para parar naquele ponto quando aquele pedaço de código for executado.
export const ModalComment = ({ action }) => {
const modalRef = useRef(null);
debugger;
return (
<>
Mas atenção! Para que o breakpoint funcione, é necessário estar com a Tab
Sources
aberta no DevTools.
Dessa forma, quando o código for executado o código irá parar naquele ponto, e então, podemos analisar as variáveis e seus respectivos valores.
Uma outra forma de adicionar breakpoints, é dentro da Tab Sources, é clicar na linha em que deseja parar e adicionar o breakpoint:
Bom saber, para mais detalhes de depuração do lado de cliente, é só consultar nesse link.
Como depurar o lado do servidor
O lado do servidor em uma aplicação Next.js é executado no servidor, utilizando Node.js.
O VSCode pode ser utilizado para depurar o lado do servidor da aplicação.
O VSCode possui várias ferramentas que nos ajudam a monitorar a execução do código do lado do servidor, como:
- Debugger: permite definir breakpoints, inspecionar variáveis e executar código passo a passo e identificar erros no código Node.js.
- Console: permite executar comandos Javascript no contexto do servidor, o que ajuda a verificar o estado da aplicação naquele momento.
- Call Stack: permite visualizar a pilha de chamadas do código em execução, identificando o contexto em que um erro ocorreu.
Como configurar o Debug no VS Code para Next.js
Passo 1: Abra o VS Code e seu projeto Next.js.
Passo 2: Criar um arquivo: ./vscode/launch.json
com o conteúdo a seguir:
{
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: debug server-side",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev"
},
{
"name": "Next.js: debug client-side",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000"
},
{
"name": "Next.js: debug full stack",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev",
"serverReadyAction": {
"pattern": "- Local:.+(https?://.+)",
"uriFormat": "%s",
"action": "debugWithChrome"
}
}
]
}
Estou usando o Yarn, sinta-se à vontade em utilizar o seu gerenciador de pacote favorito.
O comando npm run dev
pode ser substituído por yarn dev
se você estiver usando Yarn, ou por pnpm dev
se estiver usando pnpm.
Passo 3: Habilitar o debugger.
Agora vá para o painel de depuração (Ctrl+Shift+D no Windows/Linux, ⇧+⌘+D no macOS), selecione uma configuração no dropdown run and debug
, depois pressione F5 ou selecione ‘depurar’: Iniciar Depuração a partir da paleta de comandos para começar a depuração.
Escolha a opção: Next.js: debug server-side
Show! Feito isso agora, vamos testar a depuração, abra o arquivo src/actions/index.js
, na linha #7
, posicione o cursor do mouse ao lado esquerdo do número #7
e adicione o breakpoint.
export async function incrementThumbsUp(post) {
await db.post.update({
where: {
id: post.id,
},
data: {
likes: {
increment: 1,
},
},
});
revalidatePath("/");
revalidatePath(`/${post.slug}`);
}
Agora volte para o painel de depuração e clique em run and debug
: Next.js: debug server-side
. Ao fazer isso, a aplicação será iniciada, executando em http://localhost:3000/
.
Agora é o momento de testar, clicando no botão thumbs up
, pois como colocamos o breakpoint dentro do método incrementThumbsUp
, quando esse pedaço de código for executado, o debugger irá para exatamente onde deixamos o breakpoint ativo.
Então faça o teste! Eu cliquei no thumbs up
do post, “Explorando Flexbox no CSS`
Perceba que ao executar o pedaço de código que incrementa o thumbs up
o debugger parou na linha #7, e ao lado esquerdo, temos o painel, onde podemos ver o objeto post
como todas as suas propriedades e valores.
Você também pode posicionar o cursor do mouse em cima da variável post
por exemplo, dessa forma, uma pré-visualização do objeto também será mostrada:
Agora coloque um breakpoint na linha #18 do arquivo, ainda dentro da função incrementThumbsUp
e aperte play, e você verá que onde você posicionou o breakpoint, irá pausar o depurador.
Como depurar com o Next.js
Ainda no painel de depuração, temos o apoio da opção Call stack
que nos permite visualizar a pilha de chamadas do código em execução, tanto para aplicações server-side
quanto client-side
no Next.js.
É uma ferramenta poderosa para entender o fluxo do seu código e identificar problemas de depuração.
O que você verá no Call Stack:
- Uma lista de frames: Cada frame representa uma função que está sendo executada no momento.
- O nome da função: O nome da função que está sendo executada no momento.
- O local da função: O arquivo e a linha onde a função está definida, no nosso exemplo:
incrementThumbsUp
.
Uma dica para melhor aproveitamento, use o Call stack
para acompanhar o fluxo do código e identificar quais funções estão sendo chamadas.
Para mais detalhes, você pode consultar a documentação oficial, clique nesse link aqui.
Vamos fazer outro exercício?
Escolha um post, adicione um comentário a este post, após isso, acesse os detalhes deste post e vá para o final da página.
No meu caso eu respondi ao comentário “Excelente texto. Recomendo!” com o texto: “Obrigada por compartilhar!!!”
A ideia é fazer a depuração do método postReply
no src/actions/index.js
:
Coloque os breakpoints para você analisar as variáveis no momento da execução.
Dessa forma você é capaz de monitorar toda a execução do código do lado do servidor, usando o VSCode, é muito similar em relação à forma como fazemos a depuração do lado do cliente.
É possível depurar o lado do servidor no Google Chrome DevTools?
É super possível e eu vou te mostrar como fazer isso. No arquivo package.json
, você precisar passa a flag --inspect
para habilitar a depuração do Node através do DevTools do Google Chrome, o código deve ficar desta forma:
{
"scripts": {
"dev": "NODE_OPTIONS='--inspect' next dev"
}
}
Agora é só executar o comando para subir a aplicação:
yarn dev
A saída do terminal deve ser algo similar a isso:
Você pode acessar a página http://localhost:3000/ e abrir o DevTools, então repara no novo símbolo que apareceu no DevTools! Isso mesmo, do NodeJs!
Maravilha! Pode clicar no logotipo do NodeJs, onde abrirá uma nova tela, com o endereço da depuração no lado do servidor.
Por exemplo: http://127.0.0.1:9229/28c2d25b-4d26-4f0f-a6bd-10011d8280cb
. Essa string após a porta, muda pois é um id único.
Uma outra forma de acessar depois que o servidor começar a funcionar, é abrir o Chrome e entrar na barra de endereço com, chrome://inspect
.
Você vai ver a aplicação Next.js listada lá. Clique em "inspecionar" embaixo do nome da sua aplicação. Isso vai abrir uma janela nova, o DevTools.
Nessa janela, procure pela aba Sources
, então você poderá adicionar o breakpoints e monitorar a execução do código, igual fazemos quando estamos depurando o client-side
utilizando a tab Sources
no DevTools.
A única diferença: quando você procura arquivos usando Ctrl+P
ou ⌘+P
, o endereço dos arquivos vai começar com webpack://{nome-da-aplicacao}/./
.
Para maiores detalhes, eu recomendo fortemente a consulta da documentação do NextJs: Depuração.
No Windows a configuração acima, pode não funcionar corretamente, para maiores detalhes eu recomendo consultar a documentação oficial do Next.js que mostra como resolver o problema para os sistemas operacionais Windows.
Tratamento de erros e Log
Uma das formas mais simples de gerenciar erros, é utilizando try-catch
para capturar erros, pois ele ajuda a identificar e lidar com problemas que podem acontecer, especialmente quando estamos fazendo coisas que dependem de outros sistemas, como recuperar os dados do detalhe do post
.
Isso evita que a aplicação inteira pare de funcionar por causa de um erro, ou que mostremos mensagens personalizadas para os usuários.
Por exemplo, no arquivo src/app/posts/[slug]/page.js
perto da linha #11, temos o metodo getPostBySlug
, onde no corpo da função utiliza a estrutura try-catch
.
No bloco try
vamos tentar recuperar os dados do post
pelo slug
, quando um erro acontece, o bloco catch
entra em ação, ou seja, é neste momento que podemos gravar o que deu errado, por meio de logs aplicacionais ou redirecionando o usuário para uma página de erro customizada, informando-o o que aconteceu.
Faça um teste, acessando a página, a página será renderizada, ou seja o bloco try
foi executado sem erro nenhum.
No entanto, se tentarmos mudar a url para http://localhost:3000/posts/123, uma vez que o slug
123 não existe, a nossa solicitação será rejeitada e o bloco catch
será executado:
catch (error) {
logger.error("Falha ao obter o post com o slug: ", {
slug,
error,
});
redirect("/not-found");
}
Gerando um log aplicacional com o seguinte formato:
{"error":{},"level":"error","message":"Falha ao obter o post com o slug: ","slug":"123"}
Os logs são uma ferramenta essencial para identificar problemas e depurar aplicações. Você inclusive, pode conferir que na raiz do projeto, surgiu um arquivo error.log
, onde você nota o log aplicacional recém gravado.
Ou seja, graças ao método logger
no catch
que implementa o winston
que permite registrar mensagens de log em um arquivo.
Para mais detalhes veja o arquivo src/logger.js
existente na aplicação. Por fim, somos redirecionando para a página: http://localhost:3000/not-found.
No dia-a-dia de uma pessoa desenvolvedora a utilização de gerenciamento de erros, ajuda a lidar com erros e além disso, melhora absurdamente a depuração, pois fica mais fácil entender o que aconteceu.
E claro, a experiência do usuário na aplicação melhora muito, pois informamos de forma clara e amigável que houve um problema, mantendo o design e o estilo do site.
Otimização de performance no Next.js
A performance é essencial para qualquer aplicação web, e o Next.js vem equipado com várias ferramentas para melhorar a velocidade da aplicação:
- Geração de site estático (SSG): esta técnica gera páginas HTML estáticas. O resultado são páginas que carregam muito rápido, pois estão prontas para serem exibidas no navegador, ideal para conteúdos que não mudam frequentemente.
- Renderização no lado do servidor (SSR): com o SSR, as páginas são geradas no servidor a cada solicitação. Isso é útil para conteúdo dinâmico e pode melhorar significativamente a experiência de usuários com conexões lentas, já que o conteúdo é renderizado antes de chegar ao navegador.
- Otimização de imagens: o Next.js otimiza automaticamente as imagens, reduzindo o tamanho do arquivo sem perder qualidade. Isso diminui o tempo de carregamento das páginas, uma vez que imagens grandes são uma das principais causas de lentidão em websites.
- Carregamento dinâmico e lazy loading com
next/dynamic
: O Next.js permite importar componentes dinamicamente comnext/dynamic
. Isso significa que componentes podem ser carregados apenas quando são necessários, ao invés de no carregamento inicial da página. Isso reduz o tempo de carregamento inicial e melhora a performance, especialmente em páginas com muitos componentes ou scripts pesados. - Lazy loading de imagens: além da otimização automática, o Next.js suporta lazy loading de imagens. Imagens são carregadas apenas quando estão prestes a entrar na viewport, o que significa que o navegador não precisa carregar todas as imagens de uma página de uma vez, reduzindo o tempo de carregamento inicial e o uso de dados.
Como mensurar a performance?
Para analisar e melhorar a performance de um website, existem várias ferramentas úteis. As mais utilizadas e acessíveis são:
- Lighthouse: é uma ferramenta de código aberto e automatizada da Google para melhorar a qualidade de páginas web. Ela pode ser executada como uma extensão do Chrome ou dentro do Chrome DevTools. O Lighthouse fornece relatórios detalhados sobre performance, acessibilidade, práticas recomendadas para a web e SEO.
Para mais detalhes, visite a documentação oficial.
- PageSpeed Insights: também da Google, esta ferramenta analisa o conteúdo de uma página web e, em seguida, gera sugestões para torná-la mais rápida. Ela usa dados do Lighthouse mas também incorpora dados de desempenho do mundo real de usuários do Chrome (se disponíveis) para fornecer insights mais precisos.
Para mais detalhes, visite a documentação oficial.
- Aba Performance do Chrome DevTools: esta aba no Chrome DevTools é incrivelmente útil para análise de performance em tempo real. Ela permite aos desenvolvedores gravar e analisar todas as atividades que acontecem em uma página durante o carregamento. Você pode ver gráficos e detalhes sobre o tempo de carregamento, uso da CPU, uso de memória, entre outros.
Para mais detalhes, visite a documentação oficial.
- Aba Network do Chrome DevTools: embora focada em atividades de rede, esta aba também é uma ferramenta valiosa para análise de performance. Ela mostra todos os recursos que são carregados na página e quanto tempo cada um leva. Isso é útil para identificar arquivos grandes ou que demoram muito para carregar.
Conclusão
Sabe, nesse artigo sobre Next.js, a gente mergulhou nas técnicas de depuração, tanto para a parte do usuário quanto para o servidor.
Foi abordado sobre como ferramentas como o VSCode e o Chrome DevTools são importantes, além de dicas para deixar o site mais rápido e lidar melhor com os registros de erros.
Acredito que com essas técnicas, será muito mais fácil analisar o código e encontrar problemas.
Ah, e também falamos sobre como melhorar as imagens e carregar as coisas só quando precisa, para deixar tudo mais satisfatório para quem usa a aplicação. Esse artigo é uma mão na roda para quem quer ficar fera nas técnicas de depuração.
Se precisar consultar o código modificado, consulte aqui no Github. Através dessa comparação, você consegue visualizar as alterações específicas entre o projeto base e o projeto finalizado.
Espero que esta introdução às estratégias de depuração tenha sido útil e que você aproveite ao máximo as funcionalidades do Next.js e das ferramentas disponíveis que nos ajudam a entregar um trabalho incrível.
Se quiser se aprofundar no assunto
Aqui na Alura, temos vários conteúdos sobre Next, vamos conhecê-las?
Além disso, você vai aprender conceitos-chave da ferramenta e ver na prática como criar suas primeiras páginas usando o framework.
Nessa formação, trabalhamos com a versão 13 do Next. Nela, você aprenderá o que é e como construir um Design System usando as tecnologias mais populares de desenvolvimento web.
Aproveite e veja os conteúdos que a comunidade Next divulgou na última conferência.
E vamos lançar um desafio! Se você gostou desse artigo, compartilhe nas redes sociais o que você aprendeu com ele com a hashtag #AprendinoBlogdaAlura.