Angular Lazy Loading
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? SCSSApó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 :
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:
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:
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.
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.
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.


