Sitemap

Angular Lazy Loading

6 min readJan 22, 2023

--

Press enter or click to view image in full size

Tópicos

Lazy Loading é uma técnica que tem como objetivo fazer o carregamento dos recursos de acordo com a necessidade, ou seja, enquanto um determinado recurso não for requisitado ele não será carregado.

No angular é possível fazer o carregamento dos módulos de forma dinâmica, quando um determinado módulo for acessado, ele e suas dependências serão carregadas. Veremos os benefícios a seguir.

Por que usar?

Utilizar esta técnica traz algumas vantagens, tais como:

Reduz o tempo de carregamento inicial da aplicação, isto acontece pelo fato de ocorrer apenas o carregamento do módulo requisitado. Por exemplo, se o usuário acessa uma página de login, apenas o necessário para exibir a página de login será carregada.

Economiza Internet, mais uma vez, a partir do momento que se carrega só o necessário, menos arquivos serão baixados do servidor.

Recursos de processamento, ao carregar menos conteúdo, significa que tanto o servidor quanto o cliente terão menos js, css e imagens para processar.

Claro que a economia vai depender do tamanho da aplicação, dos tipos de dispositivos que a acessam e da quantidade de usuários que a utilizam. Quando falamos de dispositivos móveis, há uma percepção maior de ganho. Vamos para um exemplo prático para facilitar o entendimento.

Criando Projeto

Todo o código desenvolvido está disponível no repositório: https://github.com/vilarino/angular/tree/main/lazy-loading

A seguir os passos para criar o projeto utilizando Angular CLI:

$ ng new lazy-loading
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? SCSS

Após a criação, acesse a pasta do projeto e rode o comando especificado abaixo:

$ ng serve

--- Saída ---

✔ Browser application bundle generation complete.

Initial Chunk Files | Names | Raw Size
vendor.js | vendor | 2.10 MB |
polyfills.js | polyfills | 318.01 kB |
styles.css, styles.js | styles | 210.56 kB |
main.js | main | 49.86 kB |
runtime.js | runtime | 6.52 kB |

| Initial Total | 2.67 MB

Build at: 2023-01-21T17:44:02.783Z - Hash: 0542af3268daa8f5 - Time: 23951ms

** Angular Live Development Server is listening on localhost:4200,
open your browser on http://localhost:4200/ **

✔ Compiled successfully.

Após rodar o comando acima, o projeto deverá estar rodando na seguinte URL http://localhost:4200/.

Ao abrir a URL, deverá ser exibida a página padrão do Angular, de acordo com a imagem abaixo :

Press enter or click to view image in full size
Página padrão Angular

O conteúdo desta página fica no arquivo app.component.html, vamos limpar essa página para começarmos a criar nossos componentes. Para limpá-la, o componente app.component.html, deverá ficar apenas com o conteúdo abaixo:

Press enter or click to view image in full size
Componente App

Agora temos um projeto em angular para utilizarmos como base. Vamos ver a seguir como criar os componentes.

Criando os componentes

Inicialmente vamos criar os componentes e carregá-los normalmente, sem utilizar lazy loading. Para o nosso exemplo, vamos montar a estrutura de um blog, criando as páginas de Posts, About e Contact. Para facilitar a criação dos componentes vamos utilizar o Angular CLI.

Get Rafael Vilarino’s stories in your inbox

Join Medium for free to get updates from this writer.

Criando componente Posts.

$ ng g c pages/posts

## Saída

CREATE src/app/pages/posts/posts.component.scss (0 bytes)
CREATE src/app/pages/posts/posts.component.html (20 bytes)
CREATE src/app/pages/posts/posts.component.spec.ts (592 bytes)
CREATE src/app/pages/posts/posts.component.ts (272 bytes)
UPDATE src/app/app.module.ts (496 bytes)

Criando componente About.

$ ng g c pages/about

### Saída

CREATE src/app/pages/about/about.component.scss (0 bytes)
CREATE src/app/pages/about/about.component.html (20 bytes)
CREATE src/app/pages/about/about.component.spec.ts (592 bytes)
CREATE src/app/pages/about/about.component.ts (272 bytes)
UPDATE src/app/app.module.ts (581 bytes)

Criando compoente Contact.

$ ng g c pages/contact

### Saída

CREATE src/app/pages/contact/contact.component.scss (0 bytes)
CREATE src/app/pages/contact/contact.component.html (22 bytes)
CREATE src/app/pages/contact/contact.component.spec.ts (606 bytes)
CREATE src/app/pages/contact/contact.component.ts (280 bytes)
UPDATE src/app/app.module.ts (674 bytes)

Após criar todos os componentes, teremos a seguinte estrutura:

Estrutura do projeto, após a criação dos componentes

Uma vez criados eles deverão ser adicionados no arquivo de rota do projeto app-routing.module.ts, semelhante ao código abaixo.

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PostsComponent } from './pages/posts/posts.component';
import { AboutComponent } from './pages/about/about.component';
import { ContactComponent } from './pages/contact/contact.component';

const routes: Routes = [
{
path: 'posts',
component: PostsComponent
},
{
path: 'about',
component: AboutComponent
},
{
path: 'contact',
component: ContactComponent
}
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

Agora vamos adicionar os links para nossas páginas, vamos alterar o arquivo app.component.html, segue o código do componente.

<nav>
<ul>
<li> <a routerLink="/posts"> Posts </a></li>
<li> <a routerLink="/about"> About </a></li>
<li> <a routerLink="/contact"> Contact </a></li>
</ul>
</nav>
<router-outlet></router-outlet>

Como resultado teremos um menu com os links para as páginas e um texto abaixo informando qual componente está sendo renderizado, como demonstrado na imagem abaixo.

Press enter or click to view image in full size
Estrutura da página

Agora vamos fazer os carregamentos da páginas e observar nosso console para ver como ele se comporta.

Quando a página é carregada a primeira vez, podemos observar no console o carregamento dos recursos, no entanto quando clicamos nos outros links as páginas são carregadas normalmente, mas nenhum carregamento adicional é feito. A seguir, vamos ver como que funciona o lazy loading na prática.

Lazy Loading na prática

Como apresentado acima, criamos um projeto e adicionamos alguns componentes, sendo eles pages/posts pages/about pages/contact, agora vamos implementar o carregamento dinâmico, para isso vamos ter que fazer algumas alterações no nosso projeto.

Inicialmente vamos ajustar a rota de posts, criaremos um módulo para o componente e um módulo de rota, segue os comandos para a criação dos módulos.

$ ng g m pages/posts --routing

### Saída

CREATE src/app/pages/posts/posts-routing.module.ts (248 bytes)
CREATE src/app/pages/posts/posts.module.ts (276 bytes)

Uma vez criado os módulos, vamos ajustar o arquivo app-routing.module.ts. Ao invés de definir o componente na rota, vamos utilizar a opção loadChildren, segue o código.

Antes

{
path: 'posts',
component: PostsComponent
}

Depois

{
path: 'posts',
loadChildren: () => import('./pages/posts/posts-routing.module').then(m => m.PostsRoutingModule)
}

Após a realização desta alteração o módulo será carregado dinamicamente, no entanto o angular ainda não sabe qual componente ele deve renderizar quando a rota for chamada, precisamos especificar isso no módulo de rotas de posts (pages/posts/posts-routing.module.ts), de acordo com o código apresentado abaixo.

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PostsComponent } from './posts.component';

const routes: Routes = [
{
path: '',
component: PostsComponent
}
];

@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PostsRoutingModule { }

Neste ponto o componente será exibido corretamente. No entanto ainda falta o PostsComponent ser removido do módulo app.module.ts.

Os passos acima podem ser repetidos para os outros dois módulos. Após realizada as alterações em todos os componentes, teremos o lazy loading funcionando em nosso projeto. Segue a estrutura final do projeto.

Estrutura com os módulos por página

Como pode ser visto na imagem abaixo, de acordo com o clique no ‘menu’, o módulo do componente requisitado é carregado.

Como nem tudo são flores, a seguir vamos abordar um problema gerado com a utilização do lazy loading.

Problema

Interceptors: caso o módulo HttpClientModule seja carregado no módulo app.module.ts, os interceptors definidos em módulos internos não funcionarão.

Uma alternativa para resolver esse problema, seria importar o HttpClientModule no módulo interno que provê o interceptor, só que se estiverem usando Angular Universal, isso não vai funcionar.

Conclusão

O uso do lazy loading pode ser menos eficaz em projetos de menor escala, pois os benefícios podem ser menos perceptíveis e sua implementação pode trazer mais complexidade para o projeto. Por outro lado, em projetos maiores que carregam muitas dependências, a implementação de lazy loading pode ser mais vantajosa.-

É sempre bom ficar atento a evolução do projeto para se adotar as melhores práticas.

--

--