Depois de criar um projeto Angular, talvez tenha percebido que em algum momento do desenvolvimento a compilação vai gerar um arquivo common.js
.
Vou explicar aqui por que e quando ele passa a ser gerado.
Vamos considerar uma aplicação com algumas páginas carregadas dinamicamente (lazy load):
const routes: Routes = [
{
path: '1',
loadChildren: () => import('../pages/pagina1.module').then(m => m.Pagina1Module)
},
{
path: '2',
loadChildren: () => import('../pages/pagina2.module').then(m => m.Pagina2Module)
},
{
path: '3',
loadChildren: () => import('../pages/pagina3.module').then(m => m.Pagina3Module)
},
{
path: '4',
loadChildren: () => import('../pages/pagina4.module').then(m => m.Pagina4Module)
}
];
Cada uma dessas páginas tem a seguinte implementação (substitua mentalmente os nomes de Pagina1 por Pagina2, Pagina3 e Pagina4)
import { Component, NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
@Component({
template: 'Olá, sou a página 1 - '
})
export class Pagina1Component {
texto = 'x';
}
const routes: Routes = [{ path: '', component: Pagina1Component }]
@NgModule({
declarations: [Pagina1Component],
imports: [RouterModule.forChild(routes)]
})
export class Pagina1Module {}
Ao compilar o projeto, os seguintes chunks são gerados:
Até então não existe nenhum compartilhamento de recurso entre essas páginas.
Neste projeto temos uma pasta de strings que podem ser reaproveitadas em qualquer ponto do projeto:
strings/texto1.ts
:
export const TEXTO1 = 'TEXTO 1 - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
strings/texto2.ts
:
export const TEXTO2 = 'TEXTO 2 - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
Se referenciarmos o TEXTO1
na página 1, e o TEXTO2
na página 2, ex:
import { TEXTO1 } from "src/strings/texto1";
@Component({
template: 'Olá, sou a página 1 - '
})
export class Pagina1Component {
texto = TEXTO1;
}
e
import { TEXTO2 } from "src/strings/texto2";
@Component({
template: 'Olá, sou a página 2 - '
})
export class Pagina2Component {
texto = TEXTO2;
}
Como as duas páginas são os unicos módulos que referenciam cada um dos textos, o compilador do Angular vai embutir esses textos nos respectivos chunks. É possível perceber isso na diferença de tamanho em relação às páginas 3 e 4:
Vamos referenciar agora o TEXTO1
também na página 3 para ver o que acontece:
import { TEXTO1 } from "src/strings/texto1";
@Component({
template: 'Olá, sou a página 3 - '
})
export class Pagina3Component {
texto = TEXTO1;
}
Compilando o projeto é possível ver agora a presença do chunk common
:
O TEXTO1
foi movido para este novo chunk common
pois é compartilhado por mais de um módulo. No caso, as páginas 1 e 3 que agora possuem exatamente o mesmo tamanho, enquanto as páginas 2 e 4 mantiveram-se inalteradas.
Agora veremos o que acontece se referenciarmos o TEXTO2
na página 4. (Atualmente ele está embutido no chunk da página 2):
import { TEXTO2 } from "src/strings/texto2";
@Component({
template: 'Olá, sou a página 4 - '
})
export class Pagina4Component {
texto = TEXTO2;
}
Após compilar:
O common
ficou maior pois agora contém também o TEXTO2
que é compartilhado entre as páginas 2 e 4. Já essas duas páginas ficaram praticamente do mesmo tamanho.
O arquivo common.*.js
é criado quando um recurso é compartilhado entre dois ou mais módulos. Qualquer recurso que caia nessa situação será colocado neste chunk.
Quando for acessado o primeiro módulo lazy que compartilha recurso com outros módulos. Por exemplo, navegando para a página 1:
Sim! Existe uma opção no angular.json
onde é possível escolher por não gerar o common.js
. Neste caso, cada módulo lazy vai copiar para seu chunk os recursos que precisa.
Basta colocar a opção commonChunk
com o valor false:
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"commonChunk": false,
...
}
}
Se eu desligar esta opção no exemplo mostrado, os chunks ficam assim:
Todos ficam maiores e o common.js
foi descartado. Cada módulo copiou o TEXTO1
ou TEXTO2
para si.