Já publicou uma SPA e ao acessar uma rota aninhada ela não funcionou? Eu passei por isso recentemente, e vou te dar algumas dicas que me ajudaram.
📑
Ninguém gosta de passar por problemas enquanto está desenvolvendo software, mas faz parte, e aprendemos muito com os problemas que encontramos. Se tudo desse certo de primeira, teríamos descoberto muito menos do que sabemos.
Hoje vamos ver um problema corriqueiro relacionado a frontend que passei por esses dias, e como resolvê-lo.
Espero ajudar com a contribuição, pois procurei bastante para conseguir entender e encontrar uma solução correta, e gostaria de tornar o conhecimento disponível para mais pessoas.
Hoje muito se fala em SSR (Server Side Rendering), você constrói uma aplicação onde todas as rotas já existem, e o servidor envia as páginas compiladas e prontas para o cliente.
Mas não podemos nos esquecer das SPA's (Single Page Applications), que ainda são úteis para diversos modelos de negócio, onde não há necessidade de SEO (Search Engine Optimization) ou outras técnicas, as SPA's (Single Page Applications) são a melhor escolha, você não precisa lidar com problemas vindos com a escolha do SSR (Server Side Rendering), e pode construir as coisas com mais liberdade.
Sendo direto, eu tive um problema com rotas estáticas, utilizando o React Router DOM (v6.10), ao publicar minha aplicação em produção, minhas rotas não funcionavam após atualizar a aba do navegador. Quando eu acessava uma rota aninhada como site.com/categorias
e clicava em recarregar ou pressionava CTRL + F5
minha aplicação quebrava e retornava um 404
.
Um dos primeiros passos, foi tentar entender o motivo desse erro.
Aparentemente, é bem óbvio: podemos entender que, ao requisitar uma rota /alguma-coisa
nosso servidor (onde o frontend está hospedado) procura alguma rota mapeada com esse endereço, e como não encontra nada, retorna o erro de Not Found (404)
.
Por que o nosso servidor não encontrou nada sendo que mapeei no meu roteador as rotas e quais componentes deveriam ser renderizados?
Isso é simples, na anatomia de uma Single Page Application
, temos apenas um arquivo como entrada, no caso um arquivo index.html
que chama um script
, e injeta toda a lógica JS, fazendo assim a construção da aplicação no lado do cliente. A partir disso, o nosso router com as rotas conhecidas pode entrar em ação e fazer seu trabalho te levando para as telas mapeadas.
Logo, se tenho apenas uma entrada que é o index.html
que fica na raiz /
e o servidor está procurando por uma rota /alguma-coisa
ele não vai encontrar nada.
Existem algumas formas de resolver esse problema, e depende de como sua aplicação está estruturada, quais tecnologias você usa e como seu servidor está configurado, ou o que seu servidor fornece de configuração disponível para customização.
A solução é relativamente simples, você precisa redirecionar as rotas para a raiz, e deixar que o react-router-dom
se encarregue do resto.
Um primeiro passo é configurar o package.json
para que nosso aplicativo saiba qual é a raiz, e para isso, vamos adicionar a chave "homepage"
com o valor "/"
{
"homepage": "/"
}
Para fazer com que o servidor redirecione para a raiz, precisamos entender onde sua aplicação está hospedada, caso seja em um servidor Apache, você pode tentar um arquivo de configuração semelhante ao abaixo, para configurar os redirecionamentos:
// Nome do arquivo: .htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
Crie o arquivo com o nome .htaccess
na raiz do seu repositório ou edite-o case já exista. Esse script irá pegar as requisições de rota que não foram encontradas e irá redirecioná-las para o index.html
e então o react-router-dom
vai tomar o controle a partir de então.
Caso você use nginx
, procure o arquivo nginx.conf
(normalmente em /etc/nginx/nginx.conf
dentro do seu servidor, ou pode ser que esteja na raiz do seu repositório também), e adicione a seguinte configuração:
// Nome do arquivo: nginx.conf
location / {
try_files $uri $uri/ /index.html;
}
Esse comando irá redirecionar a solicitação para /index.html
caso o arquivo solicitado não seja encontrado.
Bom, cobrimos os cenários onde se tem um servidor próprio onde você faz a configuração diretamente (seja NGINX ou Apache), mas caso você utilize uma plataforma de hospedagem como netlify, vercel ou render, você terá que acessar seu painel de administração e procurar pelas configurações de redirecionamento.
Eu fiz essa configuração de maneira bem simples no render, então vou dar mais ênfase na configuração dele, mas vou deixar links das documentações da vercel e da netlify.
No render é bem simples, eu acessei a dashboard, fui no meu serviço (Static site), e ao clicar no serviço, foi aberta uma tela com o seguinte menu lateral:
Vá em Redirect/Rewrites
e lá encontrará a configuração para redirecionamento.
Clique em Add Rule
e preencha os campos
Você pode consultar a documentação para entender melhor como fazer essa configuração, mas o que funcionou para mim mim, e caso você esteja utilizando uma stack semelhante, irá funcionar igualmente:
Em Source
coloque o wildcard /*
, em Destination
coloque a raiz /
, e em Action
selecione Rewrite
, caso você coloque Redirect
ele irá redirecionar para a raiz sempre que uma rota solicitada, e com o Rewrite
a rota original não é alterada, sendo o que resolve nosso problema com o react-router-dom
.
E pronto, seu frontend conseguirá manipular as atualizações de rotas em produção.
Essa configuração foi feita no render, para conferir a configuração em outras plataformas pesquise por Redirect/Rewrite, e caso queira ver as documentações do netlify e vercel, veja os links abaixo:
Futuramente posso fazer um artigo ensinando essa configuração em outras plataformas (como as citadas acima). Fique de olho no blog para acompanhar os artigos.
---
Créditos da capa do artigo