Code splitting e lazy loading no React | iMasters
A maioria dos aplicativos feitos com a biblioteca React terão seus arquivos empacotados. Esse empacotamento pode ser feito com ferramentas de empacotação, por exemplo, Webpack ou Parcel (além de outras).
Realizar o empacotamento de uma aplicação é o processo onde todos os arquivos importados e usados no projeto serão mergeados para um único arquivo. Esse único arquivo é onde todo o projeto foi empacotado e mesclado – ele é o responsável por carregar a aplicação inteira de uma vez e deixá-la funcionando.
A aplicação para exemplo do artigo não tem nada de mais, apenas um sistema de rotas, onde:
/: renderiza o HomeComponent.
/a: renderiza o AComponent.
/b: renderiza o BComponent.
/c: renderiza o CComponent.
As rotas não estão sendo visíveis, pois preferi gravar apenas a aplicação em funcionamento e não o navegador de forma completa.
Mas será que podemos melhorar nossa aplicação?
Sim! Podemos melhorar o desempenho e performance da mesma – assunto do tópico a seguir.
Uma técnica muito famosa para resolver esse tipo de problema é chamada de Code Splitting (separação de código). Como funciona essa técnica? Basicamente pegamos nosso único arquivo .js que foi empacotado e o dividimos em outros pequenos arquivos (geralmente um para cada componente).
Dessa maneira, não teremos apenas um .js com todo o código necessário para que nossa aplicação funcione de forma esperada. Ao invés disso, teremos pequenos .js's separados:
A grosso modo, teremos algo parecido com o exemplo acima (não que seja assim – foi apenas um exemplo para um melhor entendimento).
Dessa forma, conseguimos carregar os componentes de forma separada. Ou seja, apenas quando forem necessários, por exemplo:
1 – Ao acessar a rota / faz o download do arquivo .js responsável pelo HomeComponent e o renderiza.
2 – Ao acessar a rota /a faz o download do arquivo .js responsável pelo AComponent e o renderiza.
3 – Ao acessar a rota /b faz o download do arquivo .js responsável pelo BComponent e o renderiza.
4 – Ao acessar a rota /c faz o download do arquivo .js responsável pelo CComponent e o renderiza.
Aqui já vemos uso de outra técnica, conhecida como Lazy Loading (carregamento preguiçoso). Em outras palavras, é a técnica realizada para carregar os arquivos .js apenas quando forem necessários (o download será feito apenas uma vez).
Chega de teoria e vamos para a prática! Hoje, na aplicação para exemplo do artigo temos um componente referente às rotas da aplicação – o Routes:
Basicamente, o mesmo está apenas importando os componentes e mapeando suas rotas. Por onde começamos a implementar o code splitting?
O primeiro passo será mudar a forma que estamos importando os componentes. Não podemos mais importá-los diretamente através dos modules (módulos).
Precisamos começar a fazer uso da função lazy do React. Para isso, devemos importá-la:
Mas, como utilizá-la? Agora nossos componentes devem ser variáveis que receberão o componente através da função lazy:
Porém, ao terminar a mudança e salvar, temos um problema:
Bom, vamos entender um pouco melhor nosso problema. Basicamente, nosso erro é:
Para resolver o problema, simplesmente podemos encapsular nossas rotas dentro do componente Suspense:
Será que agora tudo está correto? Não. Temos apenas um pequeno detalhe para corrigir. Ao carregar a aplicação, se olharmos o console do navegador:
Recebemos uma mensagem de erro. O que está acontecendo é que agora estamos passando um Object para a propriedade component do componente Route, porém, o mesmo espera que essa props seja uma função (function).
Podemos resolver o problema de forma muito simples, apenas encapsulando nossos componentes com uma arrow function:
Agora podemos utilizar e navegar pela aplicação sem erro nenhum em nosso console.
Mas, afinal, por que tivemos que utilizar o componente Suspense?
Por que foi necessário o uso do Suspense? Ele foi criado pensando em melhorar a usabilidade de nossa aplicação, geralmente enquanto uma request está sendo feita ou um componente não está pronto para ser renderizado, nós mostramos um Spinner (ou qualquer outro nome que você use) para o usuário. Dessa maneira conseguimos dizer para ele:
"Olha, calma, A aplicação está processando…".
E quando, de fato, tudo termina e está pronto, nosso componente é renderizado com suas informações.
Pensando em facilitar esse tipo de implementação para nós, desenvolvedores, foi criado o componente Suspense, que através do fallback faz exatamente isso – ele recebe um componente que será mostrado enquanto o download do arquivo .js está sendo feito e a renderização do nosso componente ainda não foi realizada.
Não percebemos muito isso, pois nossa internet é rápida, mas graças às ferramentas do Google Chrome podemos simular uma internet 3G. Assim conseguiremos ver o resultado de forma mais clara:
Para o exemplo do artigo, apenas foi passado uma tag h1 dizendo que está sendo renderizado, mas, em um exemplo do mundo real, o mesmo seria um Spinner (como eu chamo esse tipo de componente).
Neste artigo mostrei e expliquei um pouco sobre Code Splitting e Lazy Loading – duas técnicas para melhorar a performance e desempenho da nossa aplicação, pois os arquivos .js do projeto serão menores e apenas serão baixados quando forem necessários. Com isso, também conseguimos economizar um pouco da internet do usuário (caso seja móvel).
Não deixe de comentar ou me procurar em redes sociais para falarmos um pouco sobre o assunto ou tirar alguma dúvida.