Utiliza o React.lazy com confiança: Uma forma segura de carregar componentes quando estás a iterar rapidamente
React.lazy é uma excelente forma de carregar componentes sob demanda e melhorar o desempenho da tua aplicação. No entanto, por vezes pode causar alguns problemas como "ChunkLoadError" e "Falha ao carregar chunk".
O dilema
Hoje em dia, o desenvolvimento de software está a andar mais rápido sob a popular filosofia "move fast and break things". Não estamos a julgar - é simplesmente a forma como as coisas são. No entanto, este ritmo acelerado pode por vezes levar a problemas, especialmente no que diz respeito ao carregamento de componentes no React.
Se estás a trabalhar num projeto que utiliza React.lazy para carregar componentes sob demanda, podes ter encontrado alguns problemas como ChunkLoadError
e "Falha ao carregar chunk". Aqui estão algumas razões possíveis:
- Há um problema de rede, por exemplo, a ligação à internet do utilizador está lenta ou instável.
- O utilizador está numa versão obsoleta da aplicação, e o navegador está a tentar carregar um chunk que já não existe.
Geralmente, um simples refresh da página pode resolver o problema, mas não é uma ótima experiência para o utilizador. Imagina que uma tela branca aparece quando o utilizador está a navegar para outra rota - não é uma boa imagem para a tua aplicação.
Podemos equilibrar a necessidade de velocidade com a necessidade de uma experiência de utilizador suave? Claro. Deixa-me mostrar-te como (com TypeScript, claro).
A solução
Uma solução de força bruta pode ser guardar todas as versões dos chunks no servidor, assim não haverá mais o problema de "chunk em falta". À medida que a tua aplicação cresce, esta solução pode tornar-se inviável devido ao aumento das necessidades de espaço em disco, e ainda assim não resolve o problema da rede.
Dado que um retry ou um refresh pode resolver o problema, podemos implementar estas soluções no nosso código. Já que o problema geralmente acontece quando o utilizador está a navegar para outra rota, podemos resolvê-lo sem que o utilizador perceba. Tudo o que precisamos é criar um wrapper à volta da função React.lazy
que tratará dos retries e refreshes.
Já existem alguns ótimos artigos sobre como implementar este tipo de solução, por isso, vou focar-me na ideia e no funcionamento interno da solução.
Criar o wrapper
O primeiro passo é criar um wrapper à volta da função React.lazy
:
Lidar com os retries
Para problemas de rede, podemos lidar com os retries envolvendo a importFunction
numa função tryImport
:
Parece simples, certo? Também podes implementar o algoritmo de recuo exponencial para gerir os retries de forma mais eficiente.
Lidar com os refreshes
Para o problema de versões obsoletas, podemos lidar com os refreshes capturando o erro e refrescando a página:
No entanto, esta implementação é muito perigosa, pois pode causar um loop infinito de refreshes quando o erro não pode ser resolvido por um refresh. Enquanto isso, o estado da aplicação será perdido durante o refresh. Portanto, precisamos da ajuda do sessionStorage
para guardar a mensagem de que já tentámos refrescar a página:
Agora, quando capturamos o erro da função safeLazy
, sabemos que é algo que não pode ser resolvido por um refresh.
Múltiplos componentes lazy na mesma página
Ainda há uma armadilha oculta na implementação atual. Se tiveres múltiplos componentes lazy na mesma página, o loop infinito de refreshes ainda pode acontecer porque outros componentes podem redefinir o valor do sessionStorage
. Para resolver este problema, podemos utilizar uma chave única para cada componente:
Agora, cada componente terá a sua própria chave no sessionStorage
, e o loop infinito de refreshes será evitado. Podemos continuar a aperfeiçoar a solução, por exemplo:
- Reunir todas as chaves num array, de forma que só seja necessária uma chave de armazenamento.
- Definir um limite de refresh para refrescar a página mais de uma vez antes de lançar um erro.
Mas acho que já compreendes a ideia. Uma solução abrangente em TypeScript com testes e configurações está disponível no repositório do GitHub. Também publiquei o pacote react-safe-lazy
no NPM, para que possas usá-lo no teu projeto de imediato.
Conclusão
O desenvolvimento de software é um trabalho delicado, e mesmo os menores detalhes podem exigir um esforço para serem resolvidos. Espero que este artigo te ajude a lidar graciosamente com os problemas do React.lazy
e a melhorar a experiência do utilizador na tua aplicação.