Alura > Cursos de Front-end > Cursos de Angular > Conteúdos de Angular > Primeiras aulas do curso Angular 19: implementando Lazy Loading na sua aplicação

Angular 19: implementando Lazy Loading na sua aplicação

Carregamento sob demanda - Apresentação

Olá! Meu nome é Nayanne Batista e quero te dar as boas-vindas ao curso sobre Lazy Loading no Angular.

Audiodescrição: Nayanne se descreve como uma mulher de pele morena.Tem olhos castanhos e cabelos longos e lisos escuros. Usa uma camisa laranja. Ao fundo, uma estante com livros e uma iluminação degradê do azul ao rosa.

Neste curso, aprenderemos uma estratégia para otimizar o desempenho de aplicações Angular.

Pré-requisitos

Para aproveitar melhor o conteúdo, é importante ter um conhecimento básico sobre Angular, especialmente na parte de rotas, que será nosso foco principal.

Conhecendo o projeto base

Utilizaremos como projeto base o Buscante, um buscador de livros. Nele, podemos digitar, por exemplo, "Angular" no campo de busca, e serão retornados alguns livros sobre esse tema.

Interface da página inicial do site Buscante, com fundo branco e elementos em azul médio e escuro. No topo da página há uma barra de navegação com o logotipo à esquerda — que inclui o nome 'Buscante' acompanhado de um ícone de livros — e, à direita, os links 'Sobre' e 'Contato'. Centralizado na parte superior, há a pergunta 'Que livro você procura?' seguida por um campo de pesquisa estilizada com o logo do Google e a instrução 'Busque por assunto, autoria, nome...', além de um ícone de lupa. Abaixo, à esquerda, está o texto em destaque 'Busque o livro que quiser na nossa estante!', com fonte grande em negrito. À direita, uma ilustração vetorial mostra uma mulher em pé sobre uma pilha de livros, estendendo o braço para alcançar um livro em uma estante. No rodapé da página, há a inscrição 'Desenvolvido por Alura'.

Clicando em "Mais detalhes", também é possível visualizar um modal com mais informações e até mesmo ler uma prévia de um livro específico.

Estamos utilizando a API do Google Books e este projeto como ponto de partida. Além dessa busca, também temos outras rotas, como a página "Sobre" e uma página de "Contato".

Entendendo o problema

Você já acessou um site que demorou muito para carregar a primeira página? Essa é uma experiência comum e bastante frustrante. Como pessoas desenvolvedoras, não queremos que quem acesse uma aplicação que a nossa equipe desenvolva, tenha essa experiência ruim. Nosso objetivo é sempre entregar a melhor experiência possível.

Por que ocorre essa demora no carregamento inicial de tantas aplicações? Neste curso, vamos entender os motivos que causam essa demora e aprender uma solução para otimizar esse processo.

Carregamento sob demanda - Implementando Lazy Loading

Vamos entender os motivos da demora no carregamento inicial de uma aplicação e pensar em estratégias para solucioná-la. Essa demora pode ocorrer por diversos motivos.

Explorando motivos de demora no carregamento inicial

Primeiramente, o tamanho da aplicação influencia diretamente, pois quanto maior ela for, mais arquivos precisarão ser baixados, aumentando o tempo necessário para que a aplicação esteja pronta para uso.

Outro motivo é o número de dependências, ou seja, todas as bibliotecas externas e pacotes que precisam ser carregados logo no início.

Além disso, existem fatores externos à aplicação, que dizem respeito a quem usa a aplicação, como as condições de rede. Pessoas com conexões lentas, utilizando 3G ou 4G, enfrentarão um carregamento inicial mais demorado. Dispositivos com menor capacidade, como computadores e smartphones mais antigos, também podem sofrer com essa demora.

Analisando carregamento inicial com DevTools

Como não podemos controlar as condições de rede nem o dispositivo utilizado para acessar a aplicação, precisamos focar no front-end.

No navegador, vamos acessar o Buscante, abrir o DevTools com "Ctrl + Shift + J" e entrar na aba de "Rede". Se seu navegador estiver em inglês, essa aba de chamará "Network". Nos certificamos que o tipo "JS" está selecionado para filtrar as solicitações.

Ao recarregar a aplicação, todo o projeto é carregado inicialmente, incluindo componentes de modal, lista de livros, página de sobre, cabeçalho, rodapé, entre outros.

Por padrão, o Angular adota um comportamento proativo, conhecido como Eager Loading (carregamento ansioso), onde tudo que a aplicação precisa é carregado no início.

Embora esse comportamento permita acesso imediato a algumas páginas importantes, como a de busca que é a interação principal da aplicação, outras partes da aplicação não precisam estar disponíveis imediatamente, como as páginas de "Sobre" ou "Contato".

Para equilibrar essa equação, podemos dividir a aplicação em partes. Assim, conseguiremos renderizar rapidamente as principais partes da aplicação, enquanto algumas partes secundárias podem carregar sob demanda.

Escolhendo rotas para carregar sob demanda

No terminal integrado do VS Code, após baixar as dependências e executar a aplicação com ng serve, podemos visualizar os arquivos iniciais, conhecidos em inglês como initial chunk files.

Initial chunk filesNamesRaw size
polyfills.jspolyfills90.20 kB
main.jsmain60.82 kB
styles.cssstyles654 bytes

Nesse caso, são os arquivos polyfills, main com o conteúdo principal da aplicação e o styles.css, totalizando 151 kB. Tudo está sendo carregado de forma ansiosa.

Para mudar isso, precisamos dividir esses arquivos. O arquivo de rotas da aplicação, localizado em src/app/app.routes.ts, exporta uma constante do tipo Routes, que contém um objeto de rotas. Cada objeto possui seu caminho e componente correspondente que deve ser carregado.

app.routes.ts:

export const routes: Routes = [
  {
    path: 'lista-livros',
    component: ListaLivrosComponent
  },
  {
    path: 'sobre',
    component: SobreComponent
  },
  {
    path: 'contato',
    component: ContatoComponent
  },
  {
    path: '',
    redirectTo: 'lista-livros',
    pathMatch: 'full'
  },
  {
    path: '**',
    component: ListaLivrosComponent
  }
];

Configuramos as rotas de lista-livros, sobre, contatos, bem como um caminho vazio que redireciona para a listagem de livros e um rota coringa que também nos redireciona para a página principal da aplicação, que é a ListaLivrosComponent.

Atualmente, as rotas são carregadas automaticamente assim que a aplicação é inicializada. Vamos modificar essa estratégia em rotas específicas, como sobre e contato.

A escolha dessas rotas não é aleatória. A funcionalidade principal da aplicação é a pesquisa de livros, então precisamos que o carregamento ansioso ocorra para a busca e listagem de livros. As páginas de "Sobre" e "Contato", embora importantes, são secundárias e podem ser carregadas sob demanda. Pode ser que alguém acesse a apicação para buscar um livro e nem acesse essas rotas. Mas, caso sejam acessadas, precisamos garantir que estejam prontas.

Não existe uma regra fixa de onde aplicar o Lazy Loading. Você precisa avaliar quais são as rotas mais acessadas e mais importante na sua aplicação e quais são aquelas que podem ser carregadas posteriormente.

Implementando Lazy Loading

Vamos modificar a abordagem, começando pela rota sobre. Dentro do objeto, vamos apagar a propriedade component e utilizar a função loadComponent(). Assim, em vez de carregar automaticamente, faremos isso de forma dinâmica.

Depois de adicionar dois-pontos e abrir e fechar parênteses, utilizaremos a sintaxe de arrow function para fazer um import() dinâmico do JavaScript. Nele, entre aspas, passaremos o caminho do componente, ./pages/sobre/sobre.component.

Como o import retorna uma promise, usaremos o método then() com uma arrow function para acessar e carregar o componente correto, que será representado pela letra c. Com isso, conseguiremos acessar c.SobreComponent.

{
    path: 'sobre',
    loadComponent: () => import('./pages/sobre/sobre.component').then(
        (c) => c.SobreComponent
    )
},

Com essa modificação, a propriedade component que carregava o componente na inicialização foi substituída pela função loadComponent(), que realiza o carregamento dinâmico apenas quando a rota é acessada.

Também utilizamos uma arrow function e um import dinâmico do JavaScript que retorna uma promise. Diferentemente da importação estática, o componente é carregado somente quando for acessado. Para resolver a promise, foi preciso usar o método then() para carregar o componente correto.

Esssa é a sintaxe básica mais moderna do Lazy Loading (carregamento preguiçoso) no Angular, quando você está utilizando standalone components. Se você estiver usando uma abordagem modular no seu projeto, a sintaxe será diferente.

Para entender melhor sobre a mudança de sintaxe ao usar módulos, deixaremos um link de um artigo sobre Lazy Loading na atividade de "Para Saber Mais".

Agora, vamos aplicar a mesma lógica na rota de contato. Inclusive, podemos copiar o loadComponent das linhas 15 a 17 para substituir a propriedade de component do segundo objeto de rotas.

No loadComponent, vamos importar agora o componente de contato, cujo caminho é ./pages/contato/contato.component. Além disso, o componente carregado será o c.ContatoComponent.

{
    path: 'contato',
    loadComponent: () => import('./pages/contato/contato.component').then(
        (c) => c.ContatoComponent
    )
},

Por fim, podemos remover os imports que não são mais necessários, de ContatoCompoent e SobreComponent. O código final de importações ficará assim:

import { Routes } from '@angular/router';

import { ListaLivrosComponent } from './pages/lista-livros/lista-livros.component';

Analisando benefícios do Lazy Loading

No terminal, já notamos uma diferença nesse build. Antes, nós tínhamos apenas um conjunto de arquivos, o initial chunk files. Agora, temos uma divisão dos arquivos que serão carregados inicialmente e os arquivo carregados sobre demanda.

Initial chunk filesNamesRaw size
polyfills.jspolyfills90.20 kB
main.jsmain39.08 kB
styles.cssstyles654 bytes
chunk-PZ5AY32C.js-234 bytes

Inicialmente, são carregados os polyfills, que contêm scripts para compatibilidade entre navegadores, o main.js com o conteúdo principal da aplicação e o styles.css com os estilos da aplicação.

Agora, o tamanho total inicial desse pacote é de 130 kB - antes era de 151 kB. Com essa técnica, conseguimos diminuir o bundle inicial, tornando-o menor.

Além disso, também temos os lazy chunk files, ou seja, os arquivos que serão carregados sob demanda. Nesse caso, são dois: contato-component e sobre-component.

Lazy chunk filesNamesRaw size
chunk-5RJLV2AV.jscontato-component15.54 kB
chunk-N6ESHUSW.jssobre-component6.06 kB

No próprio build, conseguimos visualizar essa divisão e perceber que o pacote inicial está menor, o que resulta em um carregamento mais rápido da aplicação. É importante mencionar que, em projetos pequenos, a diferença pode não ser tão perceptível. No entanto, quanto maior a aplicação, maior será a diferença.

Vamos voltar ao navegador para visualizar a aplicação. Abriremos o DevTools com "Ctrl + Shift + J" e acessaremos a aba "Rede". Com o filtro "JS" selecionado, recarregaremos a aplicação.

Agora, podemos perceber que diversos componentes estão sendo carregados, mas não encontraremos mais o componente de contato ou sobre, pois eles não são mais carregados no início.

Quando clicamos no link "Sobre" no menu de navegação, o arquivo correspondente desse componente é carregado. Da mesma forma, quando clicamos em "Contato", o componente é carregado sob demanda, apenas quando acessamos essa rota.

A estratégia do Lazy Loading consiste em carregar componentes sob demanda, isto é, apenas quando necessários - e não no início da aplicação.

No DevTools, acessando a aba de "Desempenho", o Lazy Loading otimiza algumas métricas de desempenho. Existem diversas métricas e, por isso, deixaremos material extra para quem quiser se aprofundar. Essas métricas nos ajudam a entender o desempenho da aplicação, como o tempo para a aplicação ficar interativa ou para o primeiro conteúdo ser renderizado.

Fazendo analogias

Para ilustrar, utilizaremos uma analogia de um estudante em sala de aula. Imagine que você não seja aquele estudante que leva apenas uma caneta ou uma folha de papel, mas sim aquele que leva muitos materiais.

Você tem um armário na faculdade para guardar esses itens. Mas, sem saber se todos serão utilizados na aula, você decide agir de maneira proativa e leva tudo para a mesa.

Por conta disso, às vezes você se atrasa e perde o início da aula. Percebendo esse seu comportamento, uma professora sugere levar apenas o material essencial para a sala de aula e, caso seja necessário utilizar outro material, você pode buscá-lo sob demanda.

Essa estratégia é similar ao Lazy Loading do Angular, que carrega apenas os componentes essenciais, os quais serão necessários logo de início. Desse modo, conseguimos melhorar o desempenho da aplicação ao reduzir o tempo de inicialização, economizar recursos e carregar apenas o essencial.

Próximos passos

Neste vídeo, entendemos o que é o Lazy Loading e sua importância. Abordamos também como implementá-lo utilizando o loadComponent na abordagem dos standalone components, como verificar essa otimização com o DevTools e seu impacto positivo na performance.

Gostaríamos de saber o que você achou dessa técnica e se pretende utilizá-la em seus projetos. Compartilhe sua opinião, conte-nos o que achou desse novo formato de curso e marque-nos no LinkedIn com a hashtag #AprendiNaAlura. Participe também do Discord, pois sempre temos eventos por lá.

Te desejamos muito sucesso e até o próximo mergulho!

Sobre o curso Angular 19: implementando Lazy Loading na sua aplicação

O curso Angular 19: implementando Lazy Loading na sua aplicação possui 21 minutos de vídeos, em um total de 7 atividades. Gostou? Conheça nossos outros cursos de Angular em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Angular acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas