JavaScript-Baumschütteln, wie ein Profi

Dies ist eine Übersetzung eines Artikels über die Optimierung und Reduzierung der Größe eines Anwendungspakets. Dies ist gut, da hier bewährte Methoden beschrieben werden. Tipps, die Sie befolgen sollten, damit das Trishhing funktioniert und nicht verwendeter Code aus der Assembly entfernt wird. Es wird für viele nützlich sein, da jetzt jeder Montagesysteme verwendet, bei denen das Trishashing sofort erfolgt. Damit es jedoch richtig funktioniert, müssen Sie die unten beschriebenen Prinzipien einhalten.

Bild

Trichashing wird zur Haupttechnik, wenn Sie die Größe des Bundles reduzieren und die Anwendungsleistung unter JS verbessern müssen.

Wie Trichashing funktioniert:

  1. Sie deklarieren Importe und Exporte in jedem Modul.
  2. Der Collector (Webpack, Rollup oder ein anderer) analysiert den Abhängigkeitsbaum während der Assembly.
  3. Nicht verwendeter Code wird vom endgültigen Bundle ausgeschlossen.

Bild
Die Dienstprogrammdatei exportiert zwei Funktionen, es wird

Bild
jedoch nur initializeName verwendet. FormatName kann gelöscht werden.

Leider reicht für den korrekten Vorgang des Trishaking ein Setup des Kollektors nicht aus. Um ein besseres Ergebnis zu erzielen, müssen viele Details berücksichtigt und sichergestellt werden, dass die Module während der Optimierung nicht übersprungen wurden.

Wo soll ich anfangen?


Es gibt eine Vielzahl von Richtlinien für die Einrichtung von Trishaking. Es ist besser, mit der offiziellen Webpack- Dokumentation in das Thema einzutauchen .

Es ist erwähnenswert, dass ich vor einigen Jahren eine Boilerplate mit einer bereits konfigurierten Baugruppe und Trichashing erstellt habe. Wenn Sie also einen Ausgangspunkt für ein Projekt benötigen, kann mein Repository ein gutes Beispiel für krakenjs / grumbler sein .

Dieser Artikel beschreibt die Arbeit mit Webpack, Babel und Terser. Die meisten der vorgestellten Prinzipien funktionieren jedoch unabhängig davon, ob Sie Webpack, Rollup oder etwas anderes verwenden.

Verwenden Sie die ES6-Syntax für Importe und Exporte


Die Verwendung von ES6-Importen und -Exporten ist der erste und wichtigste Schritt zum Trichashing.

Die meisten anderen Implementierungen des "Modul" -Musters, einschließlich commonjs und require.js, sind während des Erstellungsprozesses nicht deterministisch. Mit dieser Funktion können Sammler wie Webpack nicht genau bestimmen, was importiert, was exportiert und welcher Code daher sicher gelöscht werden kann.

Bild
Optionen, die bei Verwendung von commonjs möglich sind.

Bei Verwendung von ES6-Modulen sind die Import- und Exportoptionen eingeschränkter:

  • Sie können nur auf Modulebene und nicht innerhalb der Funktion importieren und exportieren.
  • Der Modulname kann nur eine statische Zeichenfolge sein, keine Variable.
  • Alles, was Sie importieren, muss irgendwo exportiert werden.

Bild
ES6-Module haben einfachere Semantik und Verwendungsregeln.

Durch vereinfachte Regeln können Assembler genau verstehen, was importiert und exportiert wurde, und als Ergebnis bestimmen, welcher Code überhaupt nicht verwendet wird.

Erlauben Sie Babel nicht, Importe und Exporte zu transportieren


Das erste Problem, das bei der Verwendung von Babel zum Übersetzen von Code auftreten kann, ist die Standardkonvertierung von ES6-Modulen in CommonJs. Dies verhindert, dass der Kollektor den Code optimiert und zu viel wirft.

Glücklicherweise gibt es in der Babel-Konfiguration eine einfache Möglichkeit, die Modultranspilation zu deaktivieren .

Nachdem Sie dies getan haben, kann der Sammler die Transpilation von Importen und Exporten übernehmen.

Machen Sie Ihre Exporte atomar


Webpack lässt Exporte normalerweise in den folgenden Fällen intakt:

  • ;
  • ;
  • .

Solche Exporte werden entweder vollständig in das Bündel aufgenommen oder vollständig entfernt. Am Ende erhalten Sie möglicherweise ein Bundle mit Code, der niemals verwendet wird.

Bild
Beide Funktionen werden in das Bundle aufgenommen, auch wenn nur eine verwendet wird.

Bild
Und hier wird die Klasse vollständig zur Versammlung hinzugefügt.

Versuchen Sie, Ihre Exporte so klein und einfach wie möglich zu halten.

Bild
Nur die Funktion, die verwendet wird, wird in das endgültige Paket aufgenommen.

Die Implementierung dieses Hinweises ermöglicht es dem Kollektor, mehr Code auszugeben, da Sie jetzt während des Montageprozesses verfolgen können, welche Funktion importiert und verwendet wurde und welche nicht.

Dieser Tipp hilft auch dabei, Code in einem funktionaleren und wiederverwendbaren Stil zu schreiben und die Verwendung von Klassen zu vermeiden, in denen dies nicht gerechtfertigt ist.

Wenn Sie an funktionaler Programmierung interessiert sind, lesen Sie diesen Artikel .

Vermeiden Sie Nebenwirkungen auf Modulebene


Beim Schreiben von Modulen vermissen viele Menschen einen wichtigen, aber sehr heimtückischen Faktor - den Einfluss von Nebenwirkungen.

Bild
Webpack versteht nicht, was window.memoize tut, und kann diese Funktion daher nicht auslösen.

Beachten Sie, dass das obige Beispiel window.memoizezum Zeitpunkt des Imports des Moduls aufgerufen wird.

Wie Webpack es sieht:

  • ok, hier wird eine reine Add-Funktion erstellt und exportiert - vielleicht kann ich sie entfernen, wenn sie später nicht verwendet wird;
  • dann wird window.memoize aufgerufen, an das add übergeben wird;
  • Ich weiß nicht, was sie tut window.memoize, aber ich weiß, dass sie wahrscheinlich "Add" nennen und einen Nebeneffekt verursachen wird.
  • Aus Sicherheitsgründen lasse ich die Add-Funktion im Bundle, auch wenn sie sonst niemand verwendet .

In Wirklichkeit sind wir sicher, dass es sich window.memoizeum eine reine Funktion handelt, die keine Nebenwirkungen hervorruft, und Aufrufe hinzufügen, wenn jemand sie verwendet memoizedAdd.

Webpack weiß dies jedoch nicht und fügt dem endgültigen Bundle aus Gründen des Friedens die Funktion add hinzu.

Um ehrlich zu sein: Die neuesten Versionen von Webpack und Terser sind ungewöhnlich gut darin, Nebenwirkungen zu erkennen.

Bild
Wir geben Webpack mehr Informationen und erhalten ein optimiertes Bundle.

Jetzt hat der Sammler genügend Informationen zur Analyse:

  • hier memoizeauf Modulebene genannt, kann dies mit Problemen behaftet sein;
  • Die Funktion memoizestammt jedoch aus dem ES6-Import. Sie müssen sich die Funktion in ansehen util.js.
  • In der Tat sieht Memoize wie eine reine Funktion aus, es gibt keine Nebenwirkungen;
  • Wenn niemand die Funktion verwendet add, können wir sie sicher aus dem endgültigen Bundle ausschließen.

Wenn Webpack nicht genügend Informationen erhält, um eine Entscheidung zu treffen, nimmt es den sicheren Pfad und verlässt die Funktion.

Verwenden Sie Tools, um potenzielle Trishaking-Probleme zu identifizieren


Ich habe zwei Tools gefunden, um Probleme zu identifizieren.

Das erste Tool ist die Modulverkettung , ein Plugin für Webpack, mit dem Sie eine deutliche Leistungssteigerung erzielen können. Es gibt eine Debugging-Option. Es ist erwähnenswert, dass die Faktoren, die Verkettung und Trichashing verhindern, dieselben sind: zum Beispiel Nebenwirkungen auf Modulebene. Nehmen Sie die Warnungen des Plugins ernst, da jedes Problem möglicherweise die Größe des Bundles erhöht.

Das zweite ist das Plugin für den Linter https://www.npmjs.com/package/eslint-plugin-tree-shaking . Ich habe es noch nicht in mein Boilerplate integriert, da es den Fluss nicht unterstützte, als ich damit experimentierte. Er identifizierte jedoch ziemlich gut Probleme mit Trichashing.

Seien Sie vorsichtig mit Bibliotheken


Versuchen Sie, für Trichashing optimierte Bibliotheken zu verwenden. Wenn Sie beispielsweise ein großes Bündel minimierten Codes importieren jquery.min.js, besteht die Möglichkeit, dass dieses Modul nicht optimiert wird. Es ist besser, nach einem Modul zu suchen, aus dem atomare Funktionen importiert werden können, und für die Montage und Minimierung Webpack oder Rollup zu verwenden.

Manchmal können Sie eine ganze Bibliothek importieren. Wenn Sie beispielsweise den React-Produktionsbuild verwenden, müssen Sie nichts wegwerfen - alles, was darin enthalten ist, ist bereits optimiert.

Wenn Sie eine Bibliothek verwenden, die einzelne Funktionen exportiert, z. B. lodash, importieren Sie nur die erforderlichen Funktionen und stellen Sie sicher, dass die anderen vom endgültigen Bundle ausgeschlossen sind.

Verwenden Sie Build-Flags


Das DefinePlugin- Plugin für Webpack bietet eine wunderbare, aber nicht die bekannteste Funktion - die Möglichkeit zu beeinflussen, welcher Code während des Erstellungsprozesses ausgeschlossen wird.

Bild

Wenn wir es __PRODUCTION__: truean das Plugin übergeben, wird nicht nur der Funktionsaufruf validateOptions, sondern auch seine Definition aus dem endgültigen Bundle ausgeschlossen .
Dies erleichtert das Erstellen verschiedener Bundles für Entwicklung und Produktion und stellt sicher, dass der zum Debuggen bestimmte Code nicht in die Produktion gelangt.

Montage starten


Aus der Sicht ist es sehr schwierig zu bestimmen, wie Webpack ein bestimmtes Modul optimiert.

Führen Sie den Build aus, überprüfen Sie das endgültige Bundle und sehen Sie, was passiert. Schauen Sie sich den JavaScript-Code an und stellen Sie sicher, dass nichts mehr darin ist, was durch Trichashing hätte weggeworfen werden sollen.

Etwas anderes?


Wenn Sie weitere nützliche Tipps kennen, schreiben Sie dies bitte in den Kommentaren.

All Articles