Nunca é necessário enviar mais código do que o necessário para os usuários. Por isso, divida seus pacotes para garantir que isso nunca aconteça.
O método React.lazy
facilita a divisão de código de um aplicativo React em um
nível de componente usando importações dinâmicas.
import React, { lazy } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const DetailsComponent = () => (
<div>
<AvatarComponent />
</div>
)
Por que isso é útil?
Um aplicativo React grande geralmente consiste em muitos componentes, métodos utilitários e bibliotecas de terceiros. Se não houver um esforço para carregar diferentes partes de um aplicativo apenas quando necessário, um único e grande pacote de JavaScript será enviado aos usuários assim que eles carregarem a primeira página. Isso pode afetar significativamente a performance da página.
A função React.lazy
oferece uma maneira integrada de separar componentes em um
aplicativo em partes separadas de JavaScript com muito pouco trabalho. Em seguida, você pode cuidar dos estados de carregamento ao acoplar com o componente Suspense
.
Suspense
O problema de enviar um grande payload JavaScript para os usuários é o tempo que a página leva para terminar de carregar, especialmente em dispositivos e conexões de rede mais fracos. Por isso, a divisão de código e o carregamento lento são extremamente úteis.
No entanto, sempre haverá um pequeno atraso que os usuários precisam enfrentar quando
um componente de divisão de código está sendo buscado pela rede. Por isso, é importante
mostrar um estado de carregamento útil. Usar React.lazy
com o componente Suspense
ajuda a resolver esse problema.
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const renderLoader = () => <p>Loading</p>;
const DetailsComponent = () => (
<Suspense fallback={renderLoader()}>
<AvatarComponent />
</Suspense>
)
O Suspense
aceita um componente fallback
que permite mostrar qualquer componente do React
como um estado de carregamento. O exemplo a seguir mostra como isso funciona.
O avatar só é renderizado quando o botão é clicado, e uma solicitação é feita para recuperar o código necessário para o AvatarComponent
suspenso.
Enquanto isso, o componente de carregamento substituto é mostrado.
Aqui, o código que compõe AvatarComponent
é pequeno, por isso o ícone de carregamento aparece por pouco tempo. Componentes maiores podem levar muito mais tempo para carregar, especialmente em conexões de rede fracas.
Para demonstrar melhor como isso funciona:
- Para visualizar o site, pressione Ver app e depois Tela cheia
.
- Pressione "Control+Shift+J" (ou "Command+Option+J" no Mac) para abrir o DevTools.
- Clique na guia Rede.
- Clique no menu suspenso Limitação, que está definido como Nenhuma limitação por padrão. Selecione 3G rápido.
- Clique no botão Clique em mim no app.
O indicador de carregamento vai aparecer por mais tempo. Observe como todo o código que
compõe o AvatarComponent
é buscado como um fragmento separado.

Suspender vários componentes
Outro recurso do Suspense
é que ele permite suspender o carregamento de vários
componentes, mesmo que todos sejam carregados de forma lenta.
Exemplo:
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));
const renderLoader = () => <p>Loading</p>;
const DetailsComponent = () => (
<Suspense fallback={renderLoader()}>
<AvatarComponent />
<InfoComponent />
<MoreInfoComponent />
</Suspense>
)
Essa é uma maneira extremamente útil de atrasar a renderização de vários componentes enquanto mostra apenas um estado de carregamento. Quando todos os componentes terminarem de buscar, o usuário poderá ver todos eles exibidos ao mesmo tempo.
Confira com a incorporação a seguir:
Sem isso, é fácil ter o problema de carregamento escalonado, ou diferentes partes de uma interface carregando uma após a outra, cada uma com seu próprio indicador de carregamento. Isso pode tornar a experiência do usuário mais desagradável.
Lidar com falhas de carregamento
Suspense
permite mostrar um estado de carregamento temporário enquanto as solicitações de rede são feitas em segundo plano. Mas o que acontece se essas solicitações de rede falharem por algum motivo? Talvez você esteja off-line ou seu web app esteja tentando
carregar de forma lenta um URL com versão
desatualizado e não mais disponível após uma nova implantação do servidor.
O React tem um padrão para lidar com esses tipos de falhas de carregamento: usar um limite de erro. Conforme descrito na documentação,
qualquer componente do React pode servir como um limite de erro se implementar um (ou
ambos) dos métodos de ciclo de vida static getDerivedStateFromError()
ou
componentDidCatch()
.
Para detectar e processar falhas de carregamento lento, encapsule o componente Suspense
com um componente pai que sirva como um limite de erro. Dentro do método render()
do limite de erro, é possível renderizar os filhos como estão se não houver erro ou renderizar uma mensagem de erro personalizada se algo der errado:
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));
const renderLoader = () => <p>Loading</p>;
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {hasError: false};
}
static getDerivedStateFromError(error) {
return {hasError: true};
}
render() {
if (this.state.hasError) {
return <p>Loading failed! Please reload.</p>;
}
return this.props.children;
}
}
const DetailsComponent = () => (
<ErrorBoundary>
<Suspense fallback={renderLoader()}>
<AvatarComponent />
<InfoComponent />
<MoreInfoComponent />
</Suspense>
</ErrorBoundary>
)
Conclusão
Se você não souber por onde começar a aplicar a divisão de código ao seu aplicativo React, siga estas etapas:
- Comece no nível da rota. As rotas são a maneira mais simples de identificar pontos do
aplicativo que podem ser divididos. A
documentação do React
mostra como
Suspense
pode ser usado comreact-router
. - Identifique componentes grandes em uma página do seu site que só são renderizados em determinadas interações do usuário (como clicar em um botão). Dividir esses componentes minimiza os payloads JavaScript.
- Considere dividir qualquer outra coisa que esteja fora da tela e não seja essencial para o usuário.