Wie kann ich die Größe des Produktbündels verringern?


135

Ich habe eine einfache App, initialisiert von angular-cli.

Es werden einige Seiten in Bezug auf 3 Routen angezeigt. Ich habe 3 Komponenten. Auf einer Seite springt Nutzung lodashund Angular 2 HTTP - Module einige Daten (mit RxJS bekommen Observables, mapund subscribe). Ich zeige diese Elemente mit einem einfachen *ngFor.

Aber trotz der Tatsache, dass meine App wirklich einfach ist, bekomme ich ein riesiges (meiner Meinung nach) Bundle-Paket und Karten. Ich spreche allerdings nicht über gzip-Versionen, sondern über die Größe vor dem gzipping. Diese Frage ist nur eine allgemeine Empfehlung.

Einige Testergebnisse:

ng bauen

Hash: 8efac7d6208adb8641c1 Zeit: 10129 ms Chunk {0} main.bundle.js, main.bundle.map (main) 18,7 kB {3} [initial] [gerendert]

chunk {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 kB {4} [initial] [gerendert]

chunk {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 kB {4} [initial] [gerendert]

chunk {3} vendor.bundle.js, vendor.bundle.map (Anbieter) 3,96 MB [initial] [gerendert]

chunk {4} inline.bundle.js, inline.bundle.map (inline) 0 Bytes [Eintrag] [gerendert]

Warten Sie: 10 MB Vendor Bundle-Paket für eine so einfache App?

ng build --prod

Hash: 09a5f095e33b2980e7cc Zeit: 23455 ms Chunk {0} main.6273b0f04a07a1c2ad6c.bundle.js, main.6273b0f04a07a1c2ad6c.bundle.map (main) 18,3 kB {3} [initial] [gerendert]

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

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

chunk {3} vendor.07af2467307e17d85438.bundle.js, vendor.07af2467307e17d85438.bundle.map (vendor) 3.96 MB [initial] [gerendert]

chunk {4} inline.a345391d459797f81820.bundle.js, inline.a345391d459797f81820.bundle.map (inline) 0 Bytes [Eintrag] [gerendert]

Warten Sie noch einmal: So eine ähnliche Vendor-Bundle-Größe für Prod?

ng build --prod --aot

Hash: 517e4425ff872bbe3e5b Zeit: 22856 ms Chunk {0} main.95eadabace554e3c2b43.bundle.js, main.95eadabace554e3c2b43.bundle.map (main) 130 kB {3} [initial] [gerendert]

chunk {1} styles.e53a388ae1dd2b7f5434.bundle.css, styles.e53a388ae1dd2b7f5434.bundle.map, styles.e53a388ae1dd2b7f5434.bundle.map (styles) 154 kB {4} [initial] [gerendert]

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

chunk {3} vendor.41a6c1f57136df286f14.bundle.js, vendor.41a6c1f57136df286f14.bundle.map (vendor) 2.75 MB [initial] [gerendert]

chunk {4} inline.97c0403c57a46c6a7920.bundle.js, inline.97c0403c57a46c6a7920.bundle.map (inline) 0 Bytes [Eintrag] [gerendert]

ng build --aot

Hash: 040cc91df4df5ffc3c3f Zeit: 11011 ms Chunk {0} main.bundle.js, main.bundle.map (main) 130 kB {3} [initial] [gerendert]

chunk {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 kB {4} [initial] [gerendert]

chunk {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 kB {4} [initial] [gerendert]

chunk {3} vendor.bundle.js, vendor.bundle.map (Anbieter) 2,75 MB [initial] [gerendert]

chunk {4} inline.bundle.js, inline.bundle.map (inline) 0 Bytes [Eintrag] [gerendert]

Also ein paar Fragen zum Bereitstellen meiner App auf prod:

  • Warum sind die Anbieterpakete so groß?
  • Wird Baumschütteln von richtig eingesetzt angular-cli?
  • Wie kann diese Bundle-Größe verbessert werden?
  • Sind die .map-Dateien erforderlich?
  • Sind die Testfunktionen in Bundles enthalten? Ich brauche sie nicht in Prod.
  • Allgemeine Frage: Was sind die empfohlenen Tools zum Packen für Produkte? Vielleicht angular-cli(mit Webpack im Hintergrund) ist nicht die beste Option? Können wir es besser machen?

Ich habe viele Diskussionen zu Stack Overflow durchsucht, aber keine allgemeine Frage gefunden.



1
Aber ich denke nicht, dass es uns so viel ausmachen sollte, Angular-Cli wird sich entwickeln und die Dinge werden immer besser gemacht. Wenn Sie eine Funktion benötigen, die
Angular-Cli

Ich denke, @Timathon ist in gewisser Hinsicht richtig. Wenn jemand versucht, Angular2 in der Produktion bereitzustellen, sollte er sich um die Bundle-Größen kümmern, da dies die App-Leistung direkt beeinflusst. Die Checkliste für die Winkelleistung ist eine großartige Ressource, um zu sehen, was verbessert werden kann. Das eckige Team arbeitet daran, die Bündelgröße zu reduzieren. Aufgeregt zu sehen, wohin es geht!
Jack Clancy

Antworten:


72

Update Februar 2020

Da diese Antwort viel Anklang fand, dachte ich, es wäre am besten, sie mit neueren Angular-Optimierungen zu aktualisieren:

  1. Wie ein anderer Antwortender sagte, ng build --prod --build-optimizerist dies eine gute Option für Benutzer von weniger als Angular v5. Bei neueren Versionen erfolgt dies standardmäßig mitng build --prod
  2. Eine weitere Option ist die Verwendung von Modul-Chunking / Lazy Loading, um Ihre Anwendung besser in kleinere Chunks aufzuteilen
  3. Die Ivy-Rendering-Engine ist standardmäßig in Angular 9 enthalten und bietet bessere Bundle-Größen
  4. Stellen Sie sicher, dass Ihre Deps von Drittanbietern baumschüttelnd sind. Wenn Sie Rxjs v6 noch nicht verwenden, sollten Sie es sein.
  5. Wenn alles andere fehlschlägt, verwenden Sie ein Tool wie den Webpack-Bundle-Analyzer , um festzustellen , was in Ihren Modulen zu Blähungen führt
  6. Überprüfen Sie, ob Ihre Dateien komprimiert sind

Einige behaupten, dass die Verwendung der AOT-Kompilierung die Größe des Vendor-Bundles auf 250 KB reduzieren kann. In BlackHoleGalaxys Beispiel verwendet er jedoch die AOT-Kompilierung und hat immer noch eine Vendor-Bundle-Größe von 2,75 MB ng build --prod --aot, die 10x größer ist als die angenommenen 250 KB. Dies ist für Angular2-Anwendungen nicht ungewöhnlich, selbst wenn Sie v4.0 verwenden. 2,75 MB sind immer noch zu groß für alle, die sich wirklich für die Leistung interessieren, insbesondere auf einem mobilen Gerät.

Es gibt einige Dinge, die Sie tun können, um die Leistung Ihrer Anwendung zu verbessern:

1) AOT & Tree Shaking (Angular-Cli erledigt dies sofort). Mit Angular 9 ist AOT standardmäßig in der Produkt- und Entwicklungsumgebung.

2) Verwenden des serverseitigen Renderings von Angular Universal AKA (nicht in CLI)

3) Web Worker (wieder nicht in CLI, aber eine sehr gefragte Funktion)
siehe: https://github.com/angular/angular-cli/issues/2305

4) Servicemitarbeiter
sehen: https://github.com/angular/angular-cli/issues/4006

Möglicherweise benötigen Sie nicht alle diese Funktionen in einer einzigen Anwendung. Dies sind jedoch einige der Optionen, die derzeit zur Optimierung der Angular-Leistung verfügbar sind. Ich glaube / hoffe, dass Google sich der sofort einsatzbereiten Leistungsmängel bewusst ist und plant, diese in Zukunft zu verbessern.

Hier ist eine Referenz, die ausführlicher auf einige der oben genannten Konzepte eingeht:

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


Mein minimales Projekt ist 384 KB, siehe github.com/JCornat/min-angular. Ich bin sicher, es gibt eine einfache Möglichkeit, es zu optimieren, aber es liegt nahe bei 250 KB!
Jacques Cornat

2
@ JacquesCornat sieht gut aus! Ihre App hat jedoch nur eine einzige Komponente. Die Frage ist, wie Bundle-Größen oder größere Anwendungen verwaltet werden. Oft reduziert AOT die Bündelgröße nicht genug, und die Benutzer sind gezwungen, nach anderen Möglichkeiten zur Optimierung zu suchen. Ich kann jedem nur empfehlen, sich den Webpack-Bundle-Analyzer anzuschauen. Ein sehr hilfreicher / einfacher Weg, um zu sehen, was Blähungen verursacht
Jack Clancy

Leider sw-precacheweigern sich Dienstprogramme wie die Bearbeitung von Anbieterpaketen mit mehr als 2 MB.

1
@JackClancy "Die Frage ist, wie Bundle-Größen oder größere Anwendungen verwaltet werden". Nein, seine Frage lautet: "Wie kann diese Bundle-Größe verbessert werden?" und er spricht über seine minimale App mit 3 Komponenten. Wenn ich über große Bundles spreche und die AngularClass / Angular-Starter-Konfiguration verwende, wie in meinem Repo, stieg meine Bundle-Größe für große Apps von 8 MB (4 MB ohne Kartendateien) auf 580 KB.
Jacques Cornat

1
Danke, du hast mich gerettet. --prod hat die App-Größe von 6 MB auf 1,2 MB reduziert. Immer noch nicht perfekt, aber akzeptabel, da es nur für den Desktop verwendet wird.
Vyacheslav Tsivina

21

Verwenden Sie die neueste Angular-CLI- Version und den Befehl ng build --prod --build-optimizer. Dadurch wird die Build-Größe für prod env definitiv reduziert .

Dies macht der Build-Optimierer unter der Haube:

Der Build-Optimierer hat zwei Hauptaufgaben. Erstens können wir Teile Ihrer Anwendung als rein markieren. Dies verbessert das Baumschütteln, das durch die vorhandenen Tools bereitgestellt wird, und entfernt zusätzliche Teile Ihrer Anwendung, die nicht benötigt werden.

Das zweite, was der Build-Optimierer tut, ist das Entfernen von Angular-Dekoratoren aus dem Laufzeitcode Ihrer Anwendung. Dekorateure werden vom Compiler verwendet und werden zur Laufzeit nicht benötigt und können entfernt werden. Jeder dieser Jobs verringert die Größe Ihrer JavaScript-Bundles und erhöht die Startgeschwindigkeit Ihrer Anwendung für Ihre Benutzer.

Hinweis : Ein Update für Angular 5 und ng build --prodhöher , das sich automatisch um den obigen Prozess kümmert :)


1
Was
Angular

Das ist ein Problem mit Winkel / Material, auch wenn ich mit diesem Fehler konfrontiert bin. Baumschütteln nicht richtig gemacht ist wahrscheinlich die Grundursache. Mit der neuen Renderer-Engine IVY wäre das wahrscheinlich gelöst.
Shubhendu Vaid

13

Je nachdem, wie Sie daraus importieren, kann Lodash einen Fehlercode in Ihr Bundle einbringen. Beispielsweise:

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

Persönlich wollte ich immer noch kleinere Stellflächen von meinen Dienstprogrammfunktionen. flattenKann beispielsweise 1.2Knach der Minimierung bis zu Ihrem Bundle beitragen . Also habe ich eine Sammlung vereinfachter Lodash-Funktionen aufgebaut. Meine Implementierung flattenträgt dazu bei 50 bytes. Sie können hier nachsehen, ob es für Sie funktioniert: https://github.com/simontonsoftware/micro-dash


1
2 / Ich habe die "loadash-es" -Tipps aus dem obigen Kommentar ausprobiert. Es reduziert meine Bundle-Größe von 0,08 MB.
Stefdelec

Das ist nicht viel! Haben Sie noch etwas, das Lodash auf die alte Art importiert? Sie erhalten keine Hilfe, wenn nicht alles auf die neue Weise importiert wird.
Eric Simonton

Ich glaube, ich habe alles ersetzt. Die Größe hätte sich sonst nicht geändert. Ich habe unten einen weiteren Tipp gegeben (gzip-Sache), der uns wirklich geholfen hat.
Stefdelec

Interessant. Zu wie viel von Ihrem Bundle hat / hat lodash beigetragen? (ZB mit source-map-explorer.)
Eric Simonton

11

Erstens sind Anbieter-Bundles einfach deshalb riesig, weil Angular 2 auf vielen Bibliotheken basiert. Die Mindestgröße für die Angular 2-App beträgt ca. 500 KB (in einigen Fällen 250 KB, siehe unterer Beitrag).
Baumschütteln wird von richtig eingesetzt angular-cli.
Sie nicht enthalten .mapDateien, verwendet , da nur für das Debuggen. Wenn Sie ein heißes Ersatzmodul verwenden, entfernen Sie es außerdem, um den Hersteller zu entlasten.

Um für die Produktion zu packen, verwende ich persönlich Webpack (und Angular -Cli verlässt sich auch darauf ), weil Sie wirklich configure everythingfür die Optimierung oder das Debuggen können.
Wenn Sie verwenden möchten Webpack, stimme ich zu, dass es auf den ersten Blick etwas schwierig ist, aber wenn Sie sich die Tutorials im Internet ansehen, werden Sie nicht enttäuscht sein.
Andernfalls verwenden Sie angular-cli, die die Arbeit wirklich gut erledigen.

Die Verwendung der Ahead-of-Time-Kompilierung ist obligatorisch, um Apps zu optimieren und die Angular 2-App auf 250 KB zu verkleinern .

Hier ist ein Repo, das ich erstellt habe ( github.com/JCornat/min-angular ), um die minimale Winkelbündelgröße zu testen, und ich erhalte 384 KB . Ich bin sicher, dass es einen einfachen Weg gibt, es zu optimieren.

Apropos große Apps: Mit der AngularClass / Angular-Starter- Konfiguration, wie im obigen Repo, stieg meine Bundle-Größe für große Apps (über 150 Komponenten ) von 8 MB (4 MB ohne Kartendateien) auf 580 KB .


Welche spezielle Winkelstarter-Konfiguration trägt zur Reduzierung der Bundle-Größe bei? Ist es die webpack.config?
MartinJH

2
Ja, es ist die Webpack-Konfiguration, die die Bundle-Größe reduziert.
Jacques Cornat

Danke für die Klarstellung :)
MartinJH

8

Bei der folgenden Lösung wird davon ausgegangen, dass Sie Ihren dist / Ordner mit nodejs bereitstellen. Bitte verwenden Sie die folgenden app.js in der Root-Ebene

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

Stellen Sie sicher, dass Sie Abhängigkeiten installieren.

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

Erstellen Sie nun die App

ng build --prod --build-optimizer

Wenn Sie den Build weiter komprimieren möchten, z. B. 300 KB (ungefähr) reduzieren möchten, gehen Sie wie folgt vor.

Erstellen Sie einen Ordner mit dem Namen vendorinnerhalb des srcOrdners und innerhalb des Lieferantenordners. Erstellen Sie eine Datei rxjs.ts und fügen Sie den folgenden Code ein.

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

Fügen Sie dann das Folgende in die tsconfig.jsonDatei Ihrer Angular-Cli -Anwendung ein. Fügen Sie dann in compilerOptionsden folgenden json hinzu;

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

Dadurch wird Ihre Build-Größe viel zu klein. In meinem Projekt habe ich die Größe von 11 MB auf 1 MB reduziert. Ich hoffe es hilft


5

Eine Sache, die ich teilen möchte, ist, wie importierte Bibliotheken die Größe des dist erhöhen. Ich hatte ein Angular2-Moment-Paket importiert, während ich alle erforderlichen Datums- und Uhrzeitformatierungen mit der aus @ angle / common exportierten Standard-DatePipe durchführen konnte.

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

chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [initial] [gerendert] chunk {1} main.e7496551a26816427b68.bundle.js (main) 2,2 MB {3} [initial] [gerendert] chunk {2} styles.056656ed596d26ba0192.bundle.css (Stile) 69 Bytes {4} [initial] [gerendert] chunk {3} vendor.62c2cfe0ca794a5006d1.bundle.js (vendor) 3,84 MB [initial] [gerendert] chunk {4 } inline.0b9c3de53405d705e757.bundle.js (inline) 0 Bytes [Eintrag] [gerendert]

Nachdem Sie Angular2-moment entfernt und stattdessen DatePipe verwendet haben

chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [initial] [gerendert] chunk {1} main.f2b62721788695a4655c.bundle.js (main) 2,2 MB {3} [initial] [gerendert] chunk {2} styles.056656ed596d26ba0192.bundle.css (styles) 69 Bytes {4} [initial] [gerendert] chunk {3} vendor.e1de06303258c58c9d01.bundle.js (vendor) 3.35 MB [initial] [gerendert] chunk {4 } inline.3ae24861b3637391ba70.bundle.js (inline) 0 Bytes [Eintrag] [gerendert]

Beachten Sie, dass das Vendor Bundle ein halbes Megabyte reduziert hat !

Es lohnt sich zu prüfen, was eckige Standardpakete auch dann tun können, wenn Sie bereits mit einer externen Bibliothek vertraut sind.



1

Wenn Sie ausgeführt haben, ng build --prodsollten Sie überhaupt keine vendorDateien haben .

Wenn ich nur laufe, ng buildbekomme ich folgende Dateien:

Geben Sie hier die Bildbeschreibung ein

Die Gesamtgröße des Ordners beträgt ~ 14 MB. Waat! : D.

Aber wenn ich laufe, ng build --prodbekomme ich folgende Dateien:

Geben Sie hier die Bildbeschreibung ein

Die Gesamtgröße des Ordners beträgt 584 KB.

Ein und derselbe Code. Ich habe Ivy in beiden Fällen aktiviert. Winkel ist 8.2.13.

Also - ich denke, Sie haben --prodIhren Build-Befehl nicht erweitert?


1

Wenn Sie Angular 8+ verwenden und die Größe des Bundles reduzieren möchten, können Sie Ivy verwenden. Ivy ist die Standard-Ansichts-Engine in Angular 9. Gehen Sie einfach zu src / tsconfig.app.json und fügen Sie den Parameter angleCompilerOptions hinzu, zum Beispiel:

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

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

1

Dies hat die Größe in meinem Fall reduziert:

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

Für Angular 5+ ng-build --prod führt dies standardmäßig aus. Die Größe nach dem Ausführen dieses Befehls wurde von 1,7 MB auf 1,2 MB reduziert, aber für meinen Produktionszweck nicht ausreichend.

Ich arbeite auf der Facebook Messenger-Plattform und Messenger-Apps müssen kleiner als 1 MB sein, um auf der Messenger-Plattform ausgeführt zu werden. Ich habe versucht, eine Lösung für effektives Baumschütteln zu finden, aber immer noch kein Glück.


1

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


0

Ich habe eine eckige 5 + Spring Boot App (application.properties 1.3+) mit Hilfe der Komprimierung (Link unten angefügt) konnte die Größe von main.bundle.ts von 2,7 MB auf 530 KB reduzieren.

Außerdem sind --aot und --build-optimizer standardmäßig im --prod-Modus aktiviert. Sie müssen diese nicht separat angeben.

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


0

Überprüfen Sie, ob Sie eine Konfiguration mit dem Namen "Produktion" für ng build --prod haben, da dies eine Abkürzung für ng build --configuration = Produktion ist. Keine Antwort hat mein Problem gelöst, da das Problem direkt vor dem Bildschirm lag. Ich denke, das könnte durchaus üblich sein ... Ich habe die App mit i18n internationalisiert und alle Konfigurationen in zB Production-en umbenannt. Dann habe ich mit ng build --prod erstellt, unter der Annahme, dass die Standardoptimierung verwendet wird und nahezu optimal sein sollte, aber tatsächlich wurde nur ng build ausgeführt, was zu einem 7-MB-Bundle anstelle von 250 KB führte.


0

Entnommen aus den eckigen Dokumenten v9 ( https://angular.io/guide/workspace-config#alternate-build-configurations ):

Standardmäßig ist eine Produktionskonfiguration definiert, und der Befehl ng build verfügt über die Option --prod, die mit dieser Konfiguration erstellt wird. In der Produktionskonfiguration werden Standardeinstellungen festgelegt, die die App auf verschiedene Weise optimieren, z. B. das Bündeln von Dateien , das Minimieren überschüssiger Leerzeichen , das Entfernen von Kommentaren und toten Code sowie das Umschreiben von Code, um kurze, kryptische Namen zu verwenden ( "Minifizierung" ).

Darüber hinaus können Sie alle Ihre Deployables mit @ angle-builders / custom-webpack: browser builder komprimieren, wobei Ihre benutzerdefinierte webpack.config.js folgendermaßen aussieht:

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

Anschließend müssen Sie Ihren Webserver so konfigurieren, dass komprimierte Inhalte bereitgestellt werden, z. B. mit nginx, das Sie Ihrer nginx.conf hinzufügen müssen:

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

In meinem Fall schrumpfte der dist-Ordner von 25 auf 5 MB, nachdem nur --prod in ng build verwendet wurde, und schrumpfte dann nach der Komprimierung weiter auf 1,5 MB.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.