Como diminuir o tamanho do pacote de produtos?


135

Eu tenho um aplicativo simples, inicializado por angular-cli.

Ele exibe algumas páginas relativas a 3 rotas. Eu tenho 3 componentes. Em um dos desta página Eu uso lodashe angular 2 HTTP módulos para obter alguns dados (usando RxJS Observables, mape subscribe). Eu exibo esses elementos usando um simples *ngFor.

Mas, apesar do fato de meu aplicativo ser realmente simples, recebo um pacote e mapas enormes (na minha opinião). Eu não falo sobre versões do gzip, mas do tamanho antes do gzip. Esta pergunta é apenas uma consulta de recomendações gerais.

Alguns resultados de testes:

ng build

Hash: 8efac7d6208adb8641c1 Tempo: 10129ms chunk {0} main.bundle.js, main.bundle.map (main) 18,7 kB {3} [inicial] [renderizado]

pedaço {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (estilos) 155 kB {4} [inicial] [renderizado]

pedaço {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 kB {4} [inicial] [renderizado]

pedaço {3} vendor.bundle.js, vendor.bundle.map (fornecedor) 3,96 MB [inicial] [renderizado]

pedaço {4} inline.bundle.js, inline.bundle.map (inline) 0 bytes [entrada] [renderizado]

Espere: pacote de 10Mb de fornecedor para um aplicativo tão simples?

ng build --prod

Hash: 09a5f095e33b2980e7cc Tempo: 23455ms chunk {0} main.6273b0f04a07a1c2ad6c.bundle.js, main.6273b0f04a07a1c2ad6c.bundle.map (principal) 18,3 kB {3} [inicial] [processado]

pedaço {1} styles.bfdaa4d8a4eb2d0cb019.bundle.css, styles.bfdaa4d8a4eb2d0cb019.bundle.map, styles.bfdaa4d8a4eb2d0cb019.bundle.map (estilos) 154 kB {4} [inicial] [renderizado]

chunk {2} scripts.c5b720a078e5464ec211.bundle.js, scripts.c5b720a078e5464ec211.bundle.map (scripts) 128 kB {4} [inicial] [renderizado]

chunk {3} vendor.07af2467307e17d85438.bundle.js, vendor.07af2467307e17d85438.bundle.map (fornecedor) 3,96 MB [inicial] [renderizado]

pedaço {4} inline.a345391d459797f81820.bundle.js, inline.a345391d459797f81820.bundle.map (inline) 0 bytes [entrada] [renderizado]

Aguarde novamente: tamanho de pacote de fornecedor semelhante para o prod?

ng build --prod --aot

Hash: 517e4425ff872bbe3e5b Tempo: 22856ms chunk {0} main.95eadabace554e3c2b43.bundle.js, main.95eadabace554e3c2b43.bundle.map (principal) 130 kB {3} [inicial] [renderizado]

pedaço {1} styles.e53a388ae1dd2b7f5434.bundle.css, styles.e53a388ae1dd2b7f5434.bundle.map, styles.e53a388ae1dd2b7f5434.bundle.map (estilos) 154 kB {4} [inicial] [renderizado]

chunk {2} scripts.e5c2c90547f3168a7564.bundle.js, scripts.e5c2c90547f3168a7564.bundle.map (scripts) 128 kB {4} [inicial] [renderizado]

chunk {3} vendor.41a6c1f57136df286f14.bundle.js, vendor.41a6c1f57136df286f14.bundle.map (fornecedor) 2,75 MB [inicial] [renderizado]

chunk {4} inline.97c0403c57a46c6a7920.bundle.js, inline.97c0403c57a46c6a7920.bundle.map (inline) 0 bytes [entrada] [renderizado]

ng build --aot

Hash: 040cc91df4df5ffc3c3f Tempo: 11011ms chunk {0} main.bundle.js, main.bundle.map (principal) 130 kB {3} [inicial] [renderizado]

pedaço {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (estilos) 155 kB {4} [inicial] [renderizado]

pedaço {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 kB {4} [inicial] [renderizado]

pedaço {3} vendor.bundle.js, vendor.bundle.map (fornecedor) 2,75 MB [inicial] [renderizado]

pedaço {4} inline.bundle.js, inline.bundle.map (inline) 0 bytes [entrada] [renderizado]

Então, algumas perguntas para implantar meu aplicativo no prod:

  • Por que os pacotes de fornecedores são tão grandes?
  • A agitação das árvores é usada corretamente angular-cli?
  • Como melhorar esse tamanho de pacote?
  • Os arquivos .map são necessários?
  • Os recursos de teste estão incluídos nos pacotes configuráveis? Eu não preciso deles em prod.
  • Pergunta genérica: quais são as ferramentas recomendadas para empacotar para prod? Talvez angular-cli(usando o Webpack em segundo plano) não seja a melhor opção? Podemos fazer melhor?

Pesquisei muitas discussões sobre o Stack Overflow, mas não encontrei nenhuma pergunta genérica.


Para saber mais sobre otimização 2 aplicativo angular, confira este: github.com/mgechev/angular-performance-checklist#introduction
Timathon

1
Mas acho que não devemos nos importar tanto, o angular-cli evoluirá e as coisas serão feitas cada vez melhor. Se você precisar de alguma característica que angular-cli não tem, basta apresentar um problema em sua repo: github.com/angular/angular-cli
Timathon

embora eu ache que o @Timathon está certo em alguns aspectos, se alguém estiver tentando implantar o Angular2 em produção, deve se preocupar com o tamanho dos pacotes, pois isso afeta diretamente o desempenho do aplicativo. A lista de verificação de desempenho angular é um ótimo recurso para ver o que pode ser melhorado. a equipe angular está trabalhando para reduzir o tamanho dos pacotes. Animado para ver para onde vai!
Jack Clancy

Respostas:


72

Atualização fevereiro de 2020

Como essa resposta teve muita força, pensei que seria melhor atualizá-la com as otimizações Angular mais recentes:

  1. Como outro respondente disse, ng build --prod --build-optimizeré uma boa opção para pessoas que usam menos que o Angular v5. Para versões mais recentes, isso é feito por padrão comng build --prod
  2. Outra opção é usar chunking de módulo / carregamento lento para melhor dividir seu aplicativo em pedaços menores
  3. O mecanismo de renderização Ivy vem por padrão no Angular 9, oferece melhores tamanhos de pacotes
  4. Certifique-se de que os seus departamentos de terceiros sejam instáveis ​​em árvore. Se você ainda não estiver usando o Rxjs v6, deve.
  5. Se tudo mais falhar, use uma ferramenta como o webpack-bundle-analyzer para ver o que está causando inchaço em seus módulos
  6. Verifique se seus arquivos estão compactados com gzip

Algumas afirmações de que o uso da compilação AOT pode reduzir o tamanho do pacote de fornecedores para 250kb. No entanto, no exemplo do BlackHoleGalaxy, ele usa a compilação AOT e ainda fica com um tamanho de pacote de fornecedor de 2,75 MB ng build --prod --aot, 10x maior que os supostos 250kb. Isso não está fora do padrão para aplicativos angular2, mesmo se você estiver usando a v4.0. 2,75 MB ainda é muito grande para quem realmente se importa com o desempenho, especialmente em um dispositivo móvel.

Existem algumas coisas que você pode fazer para ajudar no desempenho do seu aplicativo:

1) AOT e Tree Shaking (o angular-cli faz isso imediatamente). Com o Angular 9, o AOT é por padrão no ambiente de produção e desenvolvimento.

2) Usando a renderização Angular Universal AKA no lado do servidor (não no cli)

3) Web Workers (novamente, não em cli, mas com um recurso muito solicitado),
consulte: https://github.com/angular/angular-cli/issues/2305

4) Trabalhadores de serviço,
consulte: https://github.com/angular/angular-cli/issues/4006

Você pode não precisar de todos eles em um único aplicativo, mas estas são algumas das opções que estão presentes no momento para otimizar o desempenho angular. Acredito / espero que o Google esteja ciente das deficiências prontas para uso em termos de desempenho e planeje melhorar isso no futuro.

Aqui está uma referência que fala mais profundamente sobre alguns dos conceitos mencionados acima:

https://medium.com/@areai51/the-4-stages-of-perf-tuning-for-your-angular2-app-922ce5c1b294


Meu projeto mínimo é de 384kB, consulte github.com/JCornat/min-angular. Tenho certeza de que existe uma maneira fácil de otimizá-lo, mas é perto de 250kB!
Jacques Cornat

2
@JacquesCornat parece ser bom! Mas seu aplicativo possui apenas um único componente. A questão é como gerenciar tamanhos de pacotes ou aplicativos maiores. Geralmente, o AOT não reduz o tamanho dos pacotes o suficiente e as pessoas são forçadas a procurar outra maneira de otimizar. Eu recomendo a todos que acessem o webpack-bundle-analyzer. Uma maneira muito útil / fácil de ver o que está causando inchaço
Jack Clancy

Infelizmente, utilitários como se sw-precacherecusam a lidar com pacotes de fornecedores maiores que 2 MB.

1
@JackClancy "A questão é como gerenciar tamanhos de pacotes ou aplicativos maiores". Nenhuma pergunta dele é "como melhorar esse tamanho de pacote?" e ele está falando sobre seu aplicativo mínimo com 3 componentes. De qualquer forma, falando de pacotes grandes, usando a configuração AngularClass / angular-starter, igual ao meu repo, o tamanho do meu pacote para aplicativos grandes passou de 8 MB (4 MB sem arquivos de mapa) para 580kB.
Jacques Cornat

1
Obrigado, você me salvou. --prod reduziu o tamanho do aplicativo de 6Mb para 1.2Mb. Ainda não é perfeito, mas aceita, pois é apenas para uso em desktop.
Vyacheslav Tsivina

21

Use a versão angi mais recente do cli e use o comando ng build --prod --build-optimizer Definitivamente reduzirá o tamanho da compilação para o ambiente de produção.

É isso que o otimizador de compilação faz sob o capô:

O otimizador de construção possui dois trabalhos principais. Primeiro, podemos marcar partes do seu aplicativo como puras, melhorando a agitação das árvores fornecida pelas ferramentas existentes, removendo partes adicionais do aplicativo que não são necessárias.

A segunda coisa que o otimizador de compilação faz é remover os decoradores angulares do código de tempo de execução do aplicativo. Decoradores são usados ​​pelo compilador, não são necessários em tempo de execução e podem ser removidos. Cada uma dessas tarefas diminui o tamanho dos seus pacotes configuráveis ​​JavaScript e aumenta a velocidade de inicialização do seu aplicativo para seus usuários.

Nota : Uma atualização para o Angular 5 e superior, ng build --prodcuida automaticamente do processo acima :)


1
Quanto angular 6 agora, o vendedor ainda é 4MB por apenas instalar angular / materiais e firebase
FindOutIslamNow

Esse é um problema com angular / material, mesmo eu já enfrentei esse erro. A trepidação de árvores não feita corretamente é provavelmente a causa raiz. Com o novo mecanismo de renderização IVY, provavelmente seria resolvido.
Shubhendu Vaid

13

O Lodash pode contribuir com um pedaço de código de bug para o seu pacote, dependendo de como você o importa. Por exemplo:

// includes the entire package (very large)
import * as _ from 'lodash';

// depending on your buildchain, may still include the entire package
import { flatten } from 'lodash';

// imports only the code needed for `flatten`
import flatten from 'lodash-es/flatten'

Pessoalmente, eu ainda queria pegadas menores de minhas funções utilitárias. Por exemplo, flattenpode contribuir 1.2Kcom o seu pacote, após minimização. Então, eu tenho construído uma coleção de funções lodash simplificadas. Minha implementação de flattencontribui por aí 50 bytes. Você pode conferir aqui para ver se funciona para você: https://github.com/simontonsoftware/micro-dash


1
2 / Tentei as dicas "loadash-es" do comentário acima. Reduz o tamanho do meu pacote de 0,08mb.
Stefdelec

Isso não é muito! Você ainda tem mais alguma coisa importando lodash da maneira antiga? Você não receberá ajuda a menos que tudo seja importado da nova maneira.
Eric Simonton

Eu acho que substituí tudo. O tamanho não mudaria de outra maneira. Dei outra dica abaixo (coisa do gzip) que realmente nos ajudou.
Stefdelec

Interessante. Quanto do seu pacote está contribuindo / para o lodash? (Por exemplo, utilizando source-map-explorer.)
Eric simonton

11

Em primeiro lugar, os pacotes de fornecedores são enormes simplesmente porque o Angular 2 depende de muitas bibliotecas. O tamanho mínimo para o aplicativo Angular 2 é de cerca de 500 KB (250 KB em alguns casos, consulte a publicação na parte inferior).
A trepidação de árvores é usada corretamente por angular-cli.
Você não incluem .maparquivos, porque usado apenas para depuração. Além disso, se você usar o módulo de substituição a quente, remova-o para clarear o fornecedor.

Para empacotar para produção, eu pessoalmente uso o Webpack (e o angular-cli também depende dele ), porque você pode realmente fazer configure everythingotimização ou depuração.
Se você quiser usar Webpack, eu concordo que é um pouco complicado a primeira vista, mas veja os tutoriais na rede, você não ficará desapontado.
Senão, use angular-cli, que faça o trabalho muito bem.

O uso da compilação antecipada é obrigatório para otimizar aplicativos e reduzir o aplicativo Angular 2 para 250 KB .

Aqui está um repositório que eu criei ( github.com/JCornat/min-angular ) para testar o tamanho mínimo do pacote Angular e obtenho 384kB . Estou certo de que existe uma maneira fácil de otimizá-lo.

Falando sobre aplicativos grandes, usando a configuração AngularClass / angular-starter , o mesmo do repositório acima, o tamanho do meu pacote para aplicativos grandes (mais de 150 componentes ) passou de 8 MB (4 MB sem arquivos de mapa) para 580 kB .


Que configuração angular-inicial específica é que ajuda a reduzir o tamanho do pacote? É o webpack.config?
MartinJH

2
Sim, é a configuração do webpack que reduz o tamanho do pacote.
Jacques Cornat

Obrigado pelo esclarecimento :)
MartinJH

8

A solução a seguir supõe que você esteja servindo sua dist / pasta usando o nodejs. Use o seguinte app.js no nível raiz

const express = require('express'),http = require('http'),path = require('path'),compression = require('compression');

const app = express();

app.use(express.static(path.join(__dirname, 'dist')));
app.use(compression()) //compressing dist folder 
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
})

const port = process.env.PORT || '4201';
app.set('port', port);

const server = http.createServer(app);
server.listen(port, () => console.log('Running at port ' + port))

Certifique-se de instalar dependências;

npm install compression --save
npm install express --save;

Agora construa o aplicativo

ng build --prod --build-optimizer

Se você deseja compactar ainda mais a compilação, por exemplo, reduza 300kb (aprox) de, siga o processo abaixo;

Crie uma pasta chamada vendordentro da srcpasta e dentro da pasta do fornecedor, crie um arquivo rxjs.ts e cole o código abaixo nele;

export {Subject} from 'rxjs/Subject';
export {Observable} from 'rxjs/Observable';
export {Subscription} from 'rxjs/Subscription';

E adicione o seguinte no tsconfig.jsonarquivo no seu aplicativo angular-cli. Em seguida, no compilerOptions, adicione o seguinte json;

"paths": {
      "rxjs": [
        "./vendor/rxjs.ts"
      ]
    }

Isso fará com que seu tamanho de construção seja muito menor. No meu projeto, reduzi o tamanho de 11mb para 1mb. Espero que ajude


5

Uma coisa que desejo compartilhar é como as bibliotecas importadas aumentam o tamanho da dist. Eu tinha o pacote angular2-moment importado, enquanto eu podia fazer toda a formatação de data e hora exigida usando o DatePipe padrão exportado de @ angular / common.

Com Angular2-Moment "angular2-moment": "^1.6.0",

chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [inicial] [renderizado] chunk {1} main.e7496551a26816427b68.bundle.js (principal) 2,2 MB {3} [inicial] [renderizado] chunk {2} styles.056656ed596d26ba0192.bundle.css (estilos) 69 bytes {4} [inicial] [renderizado] chunk {3} vendor.62c2cfe0ca794a5006d1.bundle.js (fornecedor) 3,84 MB [inicial] [renderizado] chunk {4 } inline.0b9c3de53405d705e757.bundle.js (embutido) 0 bytes [entrada] [renderizado]

Após remover o momento Angular2 e usar o DatePipe

chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [inicial] [renderizado] chunk {1} main.f2b62721788695a4655c.bundle.js (principal) 2,2 MB {3} [inicial] [renderizado] chunk {2} styles.056656ed596d26ba0192.bundle.css (estilos) 69 bytes {4} [inicial] [renderizado] chunk {3} vendor.e1de06303258c58c9d01.bundle.js (fornecedor) 3,35 MB [inicial] [renderizado] chunk {4 } inline.3ae24861b3637391ba70.bundle.js (embutido) 0 bytes [entrada] [renderizado]

Observe que o pacote de fornecedores reduziu meio megabyte!

O ponto é que vale a pena verificar o que os pacotes padrão angulares podem fazer, mesmo que você já esteja familiarizado com uma lib externa.



1

Se você executou ng build --prod- você não deve ter vendorarquivos.

Se eu executar apenas ng build- eu recebo esses arquivos:

insira a descrição da imagem aqui

O tamanho total da pasta é de ~ 14 MB. Waat! : D

Mas se eu executar ng build --prod- eu recebo esses arquivos:

insira a descrição da imagem aqui

O tamanho total da pasta é 584K.

Um e o mesmo código. Eu habilitei Ivy nos dois casos. Angular é 8.2.13.

Então - acho que você não adicionou --prodao seu comando de construção?


1

Se você estiver usando o Angular 8+ e quiser reduzir o tamanho do pacote, poderá usar o Ivy. Ivy vem como o mecanismo de exibição padrão no Angular 9. Vá para src / tsconfig.app.json e adicione o parâmetro angularCompilerOptions, por exemplo:

{
  "extends": ...,
  "compilerOptions":...,
  "exclude": ...,

/* add this one */ 
  "angularCompilerOptions": {
    "enableIvy": true
  }
}

1

Isso reduziu o tamanho no meu caso:

ng build --prod --build-optimizer --optimization.

Para Angular 5+ ng-build --prod faz isso por padrão. O tamanho após a execução deste comando foi reduzido de 1,7 MB para 1,2 MB, mas não o suficiente para minha finalidade de produção.

Eu trabalho na plataforma do messenger do facebook e os aplicativos do messenger precisam ter menos de 1 MB para serem executados na plataforma do messenger. Estive tentando descobrir uma solução para um tremor eficaz das árvores, mas ainda sem sorte.


1

Funciona 100% ng build --prod --aot --build-optimizer --vendor-chunk = true


0

Eu tenho um aplicativo de inicialização por mola angular de 5 + (application.properties 1.3+) com a ajuda da compactação (link anexado abaixo) foi capaz de reduzir o tamanho do tamanho do main.bundle.ts de 2,7 MB para 530 KB.

Também por padrão - aot e - build-optimizer são ativados com o modo --prod, você não precisa especificá-los separadamente.

https://stackoverflow.com/a/28216983/9491345


0

Verifique se você tem uma configuração chamada "produção" para ng build --prod, pois é uma abreviação de ng build --configuration = production Nenhuma resposta resolveu meu problema, porque o problema estava localizado exatamente em frente à tela. Eu acho que isso pode ser bastante comum ... Internacionalizei o aplicativo com o i18n renomeando todas as configurações para, por exemplo, production-en. Então eu construí com o ng build --prod assumindo que a otimização padrão é usada e deve estar próxima do ideal, mas na verdade apenas o build foi executado, resultando em um pacote de 7mb em vez de 250kb.


0

Retirado dos documentos angulares v9 ( https://angular.io/guide/workspace-config#alternate-build-configurations ):

Por padrão, uma configuração de produção é definida e o comando ng build possui a opção --prod que é criada usando essa configuração. A configuração de produção define padrões que otimizam o aplicativo de várias maneiras, como agrupar arquivos , minimizar o espaço em branco em excesso , remover comentários e código morto e reescrever o código para usar nomes curtos e enigmáticos ( "minification" ).

Além disso, você pode compactar todos os seus implementáveis ​​com o @ angular-builders / custom-webpack: construtor de navegador, onde o seu webpack.config.js personalizado se parece com o seguinte:

module.exports = {
  entry: {
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash].js'
  },
  plugins: [
    new CompressionPlugin({
      deleteOriginalAssets: true,
    })
  ]
};

Posteriormente, você terá que configurar seu servidor da web para exibir conteúdo compactado, por exemplo, com o nginx, você precisará adicionar ao seu nginx.conf:

server {
    gzip on;
    gzip_types      text/plain application/xml;
    gzip_proxied    no-cache no-store private expired auth;
    gzip_min_length 1000;
    ...
}

No meu caso, a pasta dist encolheu de 25 a 5 mb depois de usar o --prod in ng build e depois encolheu ainda mais a 1.5mb após a compactação.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.