Divisão de código com React.Lazy e Suspense

Você nunca precisa enviar mais códigos do que o necessário aos usuários, então 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 uma no nível do 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 tem muitos componentes, componentes e bibliotecas de terceiros. Se não for feito um esforço para tentar carregar diferentes partes de um aplicativo só quando são necessários, um único pacote de JavaScript será enviado aos usuários assim que eles carregarem a primeira página. Isso pode afetar significativamente o desempenho da página.

A função React.lazy fornece uma maneira integrada de separar componentes em uma aplicativo em blocos separados de JavaScript com muito pouco trabalho. Você pode cuidará dos estados de carregamento ao fazer o pareamento com o Suspense. componente.

Suspense

O problema de enviar um grande payload de JavaScript para os usuários é o comprimento o tempo que levaria para a página terminar de carregar, especialmente em dispositivos mais fracos e conexões de rede. É por isso que a divisão de código e o carregamento lento são extremamente útil.

No entanto, sempre vai haver um pequeno atraso para os usuários um componente de divisão de código está sendo buscado na rede, por isso, é importante exibir um estado de carregamento útil. Como usar React.lazy com o 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>
)

Suspense aceita um componente fallback, que permite mostrar qualquer React. como um estado de carregamento. O exemplo abaixo mostra como isso funciona. O avatar só é renderizado quando o botão é clicado, quando a solicitação é feito para recuperar o código necessário para a AvatarComponent suspensa. Enquanto isso, o componente de carregamento substituto é mostrado.

Aqui, o código que compõe AvatarComponent é pequeno, o que é por que o ícone de carregamento só aparece por um curto período. Maior podem demorar muito mais para carregar, especialmente com conexões de rede fracas.

Para demonstrar melhor como isso funciona:

  • Para visualizar o site, pressione Ver app. Em seguida, pressione Tela cheia 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 é definida como Sem limitação por padrão. Selecione 3G rápido.
  • Clique no botão Click Me no aplicativo.

O indicador de carregamento vai aparecer por mais tempo. Observe como todo o código que o AvatarComponent é buscado como um bloco separado.

Painel de rede do DevTools mostrando um arquivo chunk.js sendo baixado

Suspender vários componentes

Outro recurso do Suspense é a possibilidade de suspender vários do carregamento, mesmo que todos tenham carregamento lento.

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 forma extremamente útil de atrasar a renderização de vários componentes e, ao mesmo tempo, mostrando apenas um estado de carregamento. Assim que todos os componentes estiverem prontos busca, o usuário vê todos eles exibidos ao mesmo tempo.

Você pode ver isso com a seguinte incorporação:

Sem isso, é fácil se deparar com o problema do carregamento escalonado, ou partes diferentes de uma interface são carregadas uma após a outra, cada uma tendo o próprio indicador de carregamento. Isso pode tornar a experiência do usuário mais desagradável.

Lidar com falhas de carregamento

Suspense permite exibir um estado de carregamento temporário enquanto a rede as solicitações são feitas em segundo plano. Mas e se essas solicitações de rede falharem por algum motivo? Você pode estar off-line ou seu app da Web está tentando carregar lentamente um URL com versão desatualizados e não estão mais disponíveis após uma reimplantação do servidor.

O React tem um padrão padrão para processar esses tipos de carregamento de maneira prática. de erro: o uso de um limite de erros. Conforme descrito na documentação, qualquer componente do React poderá servir como limite de erro se implementar: (ou ambos) dos métodos de ciclo de vida static getDerivedStateFromError() ou componentDidCatch().

Para detectar e processar falhas de carregamento lento, una o Suspense com um componente pai que serve como limite de erro. Dentro do método render() do limite de erro, renderize os filhos como estão, nenhum erro ou exibir 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 React do aplicativo, siga estas etapas:

  1. Comece no nível do trajeto. Os trajetos são a forma mais simples de identificar pontos de do aplicativo que podem ser divididos. A Documentos do React mostram como Suspense pode ser usado junto com react-router
  2. Identifique os componentes grandes de uma página no seu site que só são renderizados determinadas interações do usuário (como clicar em um botão). Dividir vão minimizar seus payloads de JavaScript.
  3. Considere dividir qualquer coisa que esteja fora da tela e não seja essencial para a usuário.