Ürün paketi boyutu nasıl azaltılır?


135

İle başlatılan basit bir uygulamam var angular-cli.

3 rotaya göre bazı sayfaları görüntüler. 3 bileşenim var. Bu sayfada ne kullanımının birinde lodashbazı verileri almak için ve Eğik 2 HTTP modülleri (RxJS kullanarak Observableler, mapve subscribe). Bu unsurları basit bir *ngFor.

Ancak, uygulamamın gerçekten basit olmasına rağmen, büyük (bence) bir paket paketi ve haritalar alıyorum. Gzip sürümlerinden bahsetmiyorum ama gzip'den önceki boyut. Bu soru sadece genel bir öneri araştırmasıdır.

Bazı test sonuçları:

ng yapı

Karma: 8efac7d6208adb8641c1 Zaman: 10129ms yığın {0} main.bundle.js, main.bundle.map (ana) 18,7 kB {3} [ilk] [oluşturulmuş]

yığın {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (stiller) 155 kB {4} [ilk] [oluşturulmuş]

yığın {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 kB {4} [ilk] [oluşturulmuş]

yığın {3} vendor.bundle.js, vendor.bundle.map (satıcı) 3,96 MB [ilk] [oluşturulmuş]

yığın {4} inline.bundle.js, inline.bundle.map (satır içi) 0 bayt [giriş] [oluşturulmuş]

Bekleyin: Bu kadar basit bir uygulama için 10Mb satıcı paketi paketi?

ng build --prod

Karma: 09a5f095e33b2980e7cc Zaman: 23455ms yığın {0} main.6273b0f04a07a1c2ad6c.bundle.js, main.6273b0f04a07a1c2ad6c.bundle.map (ana) 18,3 kB {3} [başlangıç] [oluşturulmuş]

chunk {1} styles.bfdaa4d8a4eb2d0cb019.bundle.css, styles.bfdaa4d8a4eb2d0cb019.bundle.map, styles.bfdaa4d8a4eb2d0cb019.bundle.map (styles) 154 kB {4} [ilk] [rendered] [ilk]

yığın {2} scripts.c5b720a078e5464ec211.bundle.js, scripts.c5b720a078e5464ec211.bundle.map (komut dosyaları) 128 kB {4} [ilk] [oluşturulmuş]

yığın {3} vendor.07af2467307e17d85438.bundle.js, vendor.07af2467307e17d85438.bundle.map (satıcı) 3,96 MB [ilk] [oluşturulmuş]

yığın {4} inline.a345391d459797f81820.bundle.js, inline.a345391d459797f81820.bundle.map (satır içi) 0 bayt [giriş] [oluşturulmuş]

Tekrar bekleyin: üretim için bu kadar benzer bir satıcı paketi boyutu mu?

ng build --prod --aot

Karma: 517e4425ff872bbe3e5b Zaman: 22856ms yığın {0} main.95eadabace554e3c2b43.bundle.js, main.95eadabace554e3c2b43.bundle.map (ana) 130 kB {3} [başlangıç] [oluşturulmuş]

yığın {1} styles.e53a388ae1dd2b7f5434.bundle.css, styles.e53a388ae1dd2b7f5434.bundle.map, styles.e53a388ae1dd2b7f5434.bundle.map (styles) 154 kB {4} [ilk] [oluşturulmuş]

yığın {2} scripts.e5c2c90547f3168a7564.bundle.js, scripts.e5c2c90547f3168a7564.bundle.map (komut dosyaları) 128 kB {4} [ilk] [oluşturulmuş]

yığın {3} vendor.41a6c1f57136df286f14.bundle.js, vendor.41a6c1f57136df286f14.bundle.map (satıcı) 2,75 MB [ilk] [oluşturulmuş]

yığın {4} inline.97c0403c57a46c6a7920.bundle.js, inline.97c0403c57a46c6a7920.bundle.map (satır içi) 0 bayt [giriş] [oluşturulmuş]

ng build --aot

Karma: 040cc91df4df5ffc3c3f Zaman: 11011ms yığın {0} main.bundle.js, main.bundle.map (ana) 130 kB {3} [başlangıç] [oluşturulmuş]

yığın {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (stiller) 155 kB {4} [ilk] [oluşturulmuş]

yığın {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 kB {4} [ilk] [oluşturulmuş]

yığın {3} vendor.bundle.js, vendor.bundle.map (satıcı) 2,75 MB [ilk] [oluşturulmuş]

yığın {4} inline.bundle.js, inline.bundle.map (satır içi) 0 bayt [giriş] [oluşturulmuş]

Uygulamamı üretim ortamında dağıtmak için birkaç soru:

  • Satıcı paketleri neden bu kadar büyük?
  • Ağaç sallama tarafından uygun şekilde kullanılıyor angular-climu?
  • Bu paket boyutu nasıl geliştirilir?
  • .Map dosyaları gerekli mi?
  • Test özellikleri paketlere dahil mi? Onlara üretimde ihtiyacım yok.
  • Genel soru: Üretim için paketlenecek önerilen araçlar nelerdir? Belki angular-cli(arka planda Webpack kullanmak) en iyi seçenek değildir? Daha iyisini yapabilir miyiz?

Stack Overflow'da birçok tartışmayı araştırdım, ancak genel bir soru bulamadım.


Açısal 2 uygulama optimizasyonu hakkında daha fazla bilgi edinmek için şuna bakın
Timathon

1
Ama o kadar da umursamamız gerektiğini düşünmüyorum, köşeli uçlar gelişecek ve işler daha iyi ve daha iyi olacak. Angular
cli'nin

Ben @Timathon bazı açılardan doğru olduğunu düşünüyorum ederken herkes üretime Angular2 dağıtmak için çalışıyor, onlar gereken bu doğrudan uygulama performansı etkiler olarak paket boyutları önemsiyorum. Açısal performans kontrol listesi, nelerin iyileştirilebileceğini görmek için harika bir kaynaktır. açısal ekip, demet boyutlarını azaltmak için çalışıyor. Nereye gittiğini görmek için heyecanlıyım!
Jack Clancy

Yanıtlar:


73

Şubat 2020 güncellemesi

Bu yanıt çok fazla ilgi gördüğünden, onu daha yeni Açısal optimizasyonlarla güncellemenin en iyisi olacağını düşündüm:

  1. Başka bir yanıtlayanın dediği gibi, ng build --prod --build-optimizerAngular v5'ten daha az kullanan kişiler için iyi bir seçenektir. Daha yeni sürümler için bu, varsayılan olarak şu şekilde yapılır:ng build --prod
  2. Diğer bir seçenek, uygulamanızı daha küçük parçalara daha iyi bölmek için modül yığınlama / geç yükleme kullanmaktır.
  3. Ivy oluşturma motoru varsayılan olarak Angular 9'da gelir ve daha iyi paket boyutları sunar
  4. Üçüncü taraf departmanlarınızın ağaçların sarsılabilir olduğundan emin olun. Henüz Rxjs v6 kullanmıyorsanız, kullanmalısınız.
  5. Her şey başarısız olursa, webpack-bundle-analyzer gibi bir araç kullanın modüllerinizde şişkinliğe neyin sebep olduğunu görmek için
  6. Dosyalarınızın gzip'lenmiş olup olmadığını kontrol edin

Bazıları, AOT derlemesini kullanmanın, satıcı paket boyutunu 250 kb'a düşürebileceğini iddia ediyor. Bununla birlikte, BlackHoleGalaxy'nin örneğinde, AOT derlemesini kullanıyor ve hala 2.75MB'lık bir satıcı paket boyutunda kalıyor.ng build --prod --aot , sözde 250kb'den 10 kat daha büyük olan 2.75MB'lık kalıyor. Bu, v4.0 kullanıyor olsanız bile, angular2 uygulamaları için normalin dışında değildir. 2,75 MB, özellikle bir mobil cihazda performansı gerçekten önemseyen herkes için hala çok büyük.

Uygulamanızın performansına yardımcı olmak için yapabileceğiniz birkaç şey var:

1) AOT & Tree Shaking (açısal-cli bunu kutudan çıkarır). Angular 9 ile AOT, üretim ve geliştirme ortamında varsayılan olarak bulunur.

2) Angular Universal AKA sunucu tarafı oluşturmayı kullanma (cli'de değil)

3) Web Çalışanları (yine, cli'da değil, ancak çok istenen bir özellik)
bkz: https://github.com/angular/angular-cli/issues/2305

4) Hizmet Çalışanları
bkz .: https://github.com/angular/angular-cli/issues/4006

Bunların tümüne tek bir uygulamada ihtiyacınız olmayabilir, ancak bunlar, Açısal performansı optimize etmek için şu anda mevcut olan seçeneklerden bazılarıdır. Google'ın performans açısından sıra dışı eksikliklerin farkında olduğuna ve bunu gelecekte iyileştirmeyi planladığına inanıyorum / umuyorum.

İşte yukarıda bahsettiğim kavramlardan bazıları hakkında daha derinlemesine konuşan bir referans:

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


Minimal projem 384kB, bkz. Github.com/JCornat/min-angular Bunu optimize etmenin kolay bir yolu olduğundan eminim, ancak 250kB'ye yakın!
Jacques Cornat

2
@JacquesCornat iyi görünüyor! Ancak uygulamanızın yalnızca tek bir bileşeni vardır. Soru, paket boyutlarının veya daha büyük uygulamaların nasıl yönetileceğidir. Genellikle AOT, paket boyutlarını yeterince azaltmaz ve insanlar optimize etmek için başka yollara bakmaya zorlanır. Herkese web paketi paket analizcisini incelemelerini şiddetle tavsiye ederim. Şişkinliğe neyin sebep olduğunu görmenin çok yardımcı / kolay yolu
Jack Clancy

Ne yazık ki, sw-precache2MB'den büyük satıcı paketleriyle uğraşmak gibi yardımcı programlar .

1
@JackClancy "Soru, paket boyutlarının veya büyük uygulamaların nasıl yönetileceğidir". Sorusu "bu paket boyutunu nasıl geliştirebilirim?" ve 3 bileşenli minimal uygulamasından bahsediyor. Her neyse, büyük paketlerden bahsederken, AngularClass / angular-starter yapılandırmasını kullanarak, depomdakiyle aynı, büyük uygulamalar için paket boyutum 8MB'den (harita dosyaları olmadan 4MB) 580kB'ye çıktı.
Jacques Cornat

1
Teşekkürler, beni kurtardın --prod, uygulama boyutunu 6Mb'den 1.2Mb'ye düşürdü. Yine de mükemmel değil, ancak yalnızca masaüstü kullanımı için olduğu için kabul ediyor.
Vyacheslav Tsivina

21

En son açısal cli sürümünü kullanın ve command ng build --prod --build-optimizer'ı kullanın Ürün env için yapı boyutunu kesinlikle azaltacaktır .

Yapı optimize edicinin temelde yaptığı şey budur:

Yapı iyileştiricisinin iki ana görevi vardır. İlk olarak, uygulamanızın bazı kısımlarını saf olarak işaretleyebiliyoruz, bu, mevcut araçların sağladığı ağaç sarsıntısını iyileştirir ve uygulamanızın ihtiyaç duyulmayan ek parçalarını kaldırır.

Yapı iyileştiricisinin yaptığı ikinci şey, Angular dekoratörleri uygulamanızın çalışma zamanı kodundan kaldırmaktır. Dekoratörler, derleyici tarafından kullanılır ve çalışma zamanında gerekli değildir ve kaldırılabilir. Bu işlerin her biri JavaScript paketlerinizin boyutunu azaltır ve kullanıcılarınız için uygulamanızın önyükleme hızını artırır.

Not : Angular 5 ve üstü için bir güncelleme ng build --prod, yukarıdaki işlemi otomatik olarak halleder :)


1
Şu anda angular 6'ya gelince, satıcı hala yalnızca angular / material ve firebase'i yüklemek için 4MB'de
FindOutIslamNow

Bu açısal / malzeme ile ilgili bir problem, bu hatayla karşılaşsam bile. Ağaç sallamanın doğru şekilde yapılmaması muhtemelen temel nedendir. Yeni oluşturucu motoru IVY ile muhtemelen çözülecekti.
Shubhendu Vaid

13

Lodash, ondan nasıl içe aktardığınıza bağlı olarak paketinize bir hata kod parçası ekleyebilir. Örneğin:

// 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'

Şahsen ben hala fayda fonksiyonlarından daha küçük ayak izleri istiyordum. Örneğin flatten, 1.2Kküçültmeden sonra paketinize kadar katkıda bulunabilir . Ben de basitleştirilmiş lodash fonksiyonlarından oluşan bir koleksiyon oluşturuyorum. Benim uygulamam flattenkatkıda bulunuyor 50 bytes. İşinize yarayıp yaramadığını görmek için buradan kontrol edebilirsiniz: https://github.com/simontonsoftware/micro-dash


1
2 / Yukarıdaki yorumdan "yükleme" ipuçlarını denedim. Paket boyutumu 0.08mb'ye düşürüyor.
Stefdelec

Bu fazla değil! Hala eski yöntemle lodash ithal eden başka bir şey var mı? Her şey yeni şekilde içe aktarılmadıkça herhangi bir yardım almayacaksınız .
Eric Simonton

Sanırım her şeyi değiştirdim. Aksi takdirde boyut değişmezdi. Aşağıda bize gerçekten yardımcı olan başka bir ipucu verdim (gzip şeyi).
Stefdelec

İlginç. Lodash paketinizin ne kadarına katkıda bulunuyor / katkıda bulunuyor? (Örn. Kullanarak source-map-explorer)
Eric Simonton

11

İlk olarak, satıcı paketleri çok büyük çünkü Angular 2 birçok kitaplığa dayanıyor. Angular 2 uygulaması için minimum boyut yaklaşık 500 KB'tır (bazı durumlarda 250 KB, alt gönderiye bakın).
Ağaç sallama tarafından düzgün kullanılır angular-cli.
Do not dahil.map ayıklama için yalnızca kullanılan çünkü dosyaları. Ayrıca, çalışır durumda değiştirme modülü kullanıyorsanız, satıcıyı hafifletmek için çıkarın.

Üretim için paketlemek için, şahsen Webpack kullanıyorum (ve açısal-cli de ona güveniyor ), çünkü gerçekten configure everythingoptimizasyon veya hata ayıklama için yapabilirsiniz .
Kullanmak istiyorsanız Webpack, ilk bakışta biraz zor olduğunu kabul ediyorum, ancak internette eğitimleri görün, hayal kırıklığına uğramayacaksınız.
Aksi angular-clitakdirde, işi gerçekten iyi yapan kullanın.

Kullanılması derleme of-time-Ahead optimize uygulamalar zorunludur, ve Açısal 2 uygulamasını küçültmek 250KB .

İşte minimum Angular paket boyutunu test etmek için oluşturduğum bir repo ( github.com/JCornat/min-angular ) ve 384kB elde ediyorum . Bunu optimize etmenin kolay bir yolu olduğundan eminim.

Kullanarak, büyük uygulamalar hakkında konuşmak AngularClass / açısal-marş konfigürasyonunu, repo aynı yukarıdaki, büyük uygulamalar (benim paket büyüklüğü 150 + bileşenleri ) gitti 8MB için (harita dosyaları olmadan 4MB) 580KB .


Paket boyutunu küçültmeye yardımcı olan hangi özel açısal başlangıç ​​yapılandırmasıdır? Webpack.config mi?
MartinJH

2
Evet, paket boyutunu küçülten web paketi yapılandırmasıdır.
Jacques Cornat

Açıklama için teşekkürler :)
MartinJH

8

Aşağıdaki çözüm, nodejs kullanarak dist / klasörünüze hizmet verdiğinizi varsayar. Lütfen aşağıdaki app.js'yi kök düzeyinde kullanın

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))

Bağımlılıkları yüklediğinizden emin olun;

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

Şimdi uygulamayı oluşturun

ng build --prod --build-optimizer

Yapıyı daha fazla sıkıştırmak istiyorsanız, 300kb'den (yaklaşık) azaltın deyin, ardından aşağıdaki işlemi izleyin;

Klasörün vendoriçinde srcve satıcı klasörünün içinde bir klasör oluşturun rxjs.ts ve aşağıdaki kodu içine yapıştırın;

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

Ve sonra follwing'i tsconfig.jsonaçısal-cli uygulamanızda dosyaya ekleyin . Ardından compilerOptions, aşağıdaki json'u ekleyin;

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

Bu, yapı boyutunuzu çok daha küçük hale getirecektir. Projemde boyutu 11mb'den 1mb'ye düşürdüm. Umarım yardımcı olur


5

Paylaşmak istediğim bir şey, içe aktarılan kütüphanelerin uzaklığın boyutunu nasıl artırdığıdır. Angular2-moment paketimi içe aktarmıştım, oysa @ angular / common'dan dışa aktarılan standart DatePipe'ı kullanarak ihtiyacım olan tüm tarih ve saat biçimlendirmesini yapabiliyordum.

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

yığın {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [ilk] [oluşturulmuş] yığın {1} main.e7496551a26816427b68.bundle.js (ana) 2,2 MB {3} [ilk] [oluşturulmuş] yığın {2} styles.056656ed596d26ba0192.bundle.css (stiller) 69 bayt {4} [ilk] [oluşturulmuş] yığın {3} vendor.62c2cfe0ca794a5006d1.bundle.js (satıcı) 3,84 MB [başlangıç] [oluşturulmuş] yığın {4 } inline.0b9c3de53405d705e757.bundle.js (satır içi) 0 bayt [giriş] [oluşturulmuş]

Angular2-moment'i kaldırdıktan ve bunun yerine DatePipe'ı kullandıktan sonra

yığın {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [ilk] [oluşturulmuş] yığın {1} main.f2b62721788695a4655c.bundle.js (ana) 2,2 MB {3} [ilk] [oluşturulmuş] yığın {2} styles.056656ed596d26ba0192.bundle.css (stiller) 69 bayt {4} [ilk] [oluşturulmuş] yığın {3} vendor.e1de06303258c58c9d01.bundle.js (satıcı) 3,35 MB [başlangıç] [oluşturulmuş] yığın {4 } inline.3ae24861b3637391ba70.bundle.js (satır içi) 0 bayt [giriş] [oluşturulmuş]

Satıcı paketinin yarım megabayt düşürdüğünü unutmayın !

Demek istediğim, harici bir kütüphaneye zaten aşina olsanız bile açısal standart paketlerin neler yapabileceğini kontrol etmeye değer.



1

Eğer koştuysanız ng build --prod- hiç vendordosyalarınız olmamalı .

Sadece koşarsam ng build- şu dosyaları alırım:

görüntü açıklamasını buraya girin

Klasörün toplam boyutu ~ 14MB'dir. Waat! : D

Ama çalıştırırsam ng build --prod- şu dosyaları alırım:

görüntü açıklamasını buraya girin

Klasörün toplam boyutu 584K'dır.

Bir ve aynı kod. Her iki durumda da Ivy'yi etkinleştirdim. Açısal 8.2.13'tür.

Öyleyse - --prodinşa komutuna eklemedin sanırım ?


1

Angular 8+ kullanıyorsanız ve paketin boyutunu küçültmek istiyorsanız Ivy'yi kullanabilirsiniz. Ivy, Angular 9'da varsayılan görünüm motoru olarak gelir. Src / tsconfig.app.json adresine gidin ve angularCompilerOptions parametresini ekleyin, örneğin:

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

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

1

Bu benim durumumda boyutu küçülttü:

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

Angular 5+ ng-build için --prod bunu varsayılan olarak yapar. Bu komutu çalıştırdıktan sonra boyut 1.7MB'den 1.2MB'ye düşürüldü, ancak üretim amacım için yeterli değil.

Facebook messenger platformunda çalışıyorum ve messenger uygulamalarının messenger platformunda çalışması için 1MB'den küçük olması gerekiyor. Etkili ağaç sarsıntısı için bir çözüm bulmaya çalışıyorum ama yine de şans yok.


1

Çalışmaları% 100 ng build --prod --aot --build-optimizer --vendor-chunk = true


0

Açısal bir 5 + yaylı önyükleme uygulamam var (application.properties 1.3+) sıkıştırma yardımı ile (aşağıya eklenen bağlantı) main.bundle.ts boyutunu 2.7 MB'den 530 KB'ye düşürmeyi başardı.

Ayrıca, --aot ve --build-optimizer varsayılan olarak --prod modunda etkinleştirilir, bunları ayrı ayrı belirtmenize gerek yoktur.

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


0

Ng build --prod için "üretim" adlı yapılandırmanızın olup olmadığını kontrol edin, çünkü bu, ng build --configuration = production için bir kısaltmadır. Hiçbir yanıt sorunum çözülmedi, çünkü sorun ekranın hemen önünde duruyordu . Bunun oldukça yaygın olabileceğini düşünüyorum ... i18n ile uygulamayı uluslararasılaştırdım, tüm yapılandırmaları örneğin production-en olarak yeniden adlandırdım. Daha sonra, varsayılan optimizasyonun kullanıldığını ve optimal düzeye yakın olması gerektiğini varsayarak ng build --prod ile inşa ettim, ancak aslında sadece ng yapının yürütüldüğünü ve bunun sonucunda 250kb yerine 7mb'lik bir paket oluşturdum.


0

Angular docs v9'dan alınmıştır ( https://angular.io/guide/workspace-config#alternate-build-configurations ):

Varsayılan olarak, bir üretim konfigürasyonu tanımlanmıştır ve ng build komutunun, bu konfigürasyonu kullanarak inşa eden --prod seçeneği vardır. Gibi yollarla, bir dizi uygulamayı optimize üretim yapılandırma setleri varsayılan dosya donatılacak , aşırı boşluk minimize , yorum ve ölü kodunu kaldırarak , şifreli isimler (ve Kullan Short kod yeniden yazma "minification" ).

Ek olarak, tüm konuşlandırılabilirlerinizi @ angular-builders / custom-webpack: browser builder ile sıkıştırabilirsiniz; burada özel webpack.config.js şuna benzer:

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

Daha sonra, web sunucunuzu sıkıştırılmış içerik sunacak şekilde yapılandırmanız gerekecektir, örneğin nginx ile nginx.conf dosyanıza eklemeniz gerekir:

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

Benim durumumda dist klasörü, sadece --prod in ng yapısını kullandıktan sonra 25'ten 5 mb'ye ve daha sonra sıkıştırmadan sonra 1.5mb'ye küçüldü.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.