Mit Webpack das Traumbündel sammeln

JS-Anwendungen, Websites und andere Ressourcen werden immer komplexer und Build-Tools sind die Realität der Webentwicklung. Bundler helfen beim Packen, Kompilieren und Organisieren von Bibliotheken. Eines der leistungsstarken und flexiblen Open Source-Tools, das perfekt zum Erstellen der Clientanwendung angepasst werden kann, ist Webpack.

Maxim Sosnov ( crazymax11 ) - Frontend Lead in N1.RU führte Webpack in mehrere große Projekte ein, die zuvor einen eigenen Build hatten, und trug mehrere Projekte dazu bei. Maxim weiß, wie man mit Webpack ein Traumpaket erstellt, es schnell erledigt und so konfiguriert, dass die Konfiguration sauber, unterstützt und modular bleibt.


Die Interpretation unterscheidet sich vom Bericht - es handelt sich um eine stark verbesserte Version der Proflinks. Während des gesamten Transkripts sind Ostereier auf Artikeln, Plugins, Minifiers, Optionen, Transpilern und Beweisen der Wörter des Sprechers verteilt, auf die Links einfach nicht in eine Rede gesetzt werden können. Wenn du alles sammelst, öffnet sich das Bonuslevel in Webpack :-)

Webpack-Integration in ein typisches Projekt


Normalerweise ist die Implementierungsprozedur wie folgt: Der Entwickler liest irgendwo einen Artikel über Webpack, beschließt, eine Verbindung herzustellen, beginnt mit dem Erstellen, funktioniert irgendwie, alles beginnt und für einige Zeit funktioniert die Webpack-Konfiguration - für sechs Monate, ein Jahr, zwei. Vor Ort ist alles in Ordnung - Sonne, Regenbogen und Schmetterlinge. Und dann kommen echte Benutzer:

- Von Mobilgeräten wird Ihre Site nicht geladen.
- Bei uns funktioniert alles. Vor Ort ist alles in Ordnung!

Für den Fall, dass der Entwickler alles profiliert und feststellt, dass das Bundle für mobile Geräte 7 MB wiegt und das Laden 30 Sekunden dauert . Dies passt zu niemandem und der Entwickler beginnt zu suchen, wie das Problem gelöst werden kann - er kann einen Loader anschließen oder ein magisches Plug-In finden, das alle Probleme löst. Wie durch ein Wunder befindet sich ein solches Plugin. Unser Entwickler geht zur Webpack-Konfiguration und versucht zu installieren, aber die Codezeile stört:

if (process.env.NODE_ENV === 'production') { config.module.rules[7].options.magic = true; } 

Die Zeile wird wie folgt übersetzt: "Wenn die Konfiguration für die Produktion zusammengestellt wird, nehmen Sie die siebte Regel und setzen Sie dort die Option magic = true ." Der Entwickler weiß nicht, was er damit anfangen soll und wie er es lösen soll. Dies ist eine Situation, in der Sie ein Bündel Träume brauchen.

Wie sammle ich ein Bündel Träume?


Definieren wir zunächst, was es ist. Erstens hat das Traumbündel zwei Hauptmerkmale:

  • Es wiegt ein wenig . Je weniger Gewicht - desto schneller erhält der Benutzer eine funktionierende Anwendung. Sie möchten nicht, dass Ihre Site 15 Sekunden lang geöffnet wird.
  • Der Benutzer lädt nur das herunter, was heruntergeladen werden muss, um die aktuelle Seite der Site anzuzeigen, und kein Byte mehr!

Um die Größe des Bundles zu verringern, müssen Sie zunächst dessen Größe bewerten.

Bundle-Größe bewerten


Die beliebteste Lösung ist das WebpackBundleAnalyzer- Plugin. Es sammelt Statistiken zur Anwendungserstellung und rendert eine interaktive Seite, auf der Sie die Position und das Gewicht jedes Moduls sehen können.

Bild

Wenn dies nicht ausreicht, können Sie mit einem anderen Plugin ein Abhängigkeitsdiagramm erstellen.

Bild

Oder ein Kreisdiagramm .

Bild

Wenn dies nicht ausreicht und Sie Webpack an Vermarkter verkaufen möchten, können Sie ein ganzes Universum aufbauen, in dem jeder Punkt ein Modul ist, wie ein Stern im Universum.

Bild

Es gibt viele Tools, die die Größe des Bundles bewerten und überwachen. In der Webpack-Konfiguration gibt es eine Option, die die Assembly zum Absturz bringt , wenn das Bundle beispielsweise zu viel wiegt. Es gibt ein Duplikat-Paket-Prüfer-Webpack-Plugin-Plugin , das Sie daran hindert, ein Bundle zu erstellen , wenn Sie 2 npm-Pakete verschiedener Versionen haben, z. B. Lodash 4.15 und Lodash 4.14.

So reduzieren Sie das Bundle


  • Am naheliegendsten ist es, UglifyJS so anzuschließen , dass JavaScript minimiert wird.
  • Verwenden Sie spezielle Loader und Plugins , die eine bestimmte Ressource komprimieren und optimieren. Zum Beispiel css-nano für css oder SVGO , das SVG optimiert.
  • Komprimieren Sie alle Dateien über gzip / brotli-Plugins direkt in Webpack.
  • Andere Werkzeuge.

Jetzt werden wir verstehen, wie man überschüssiges Material aus dem Bündel wirft.

Wirf den Überschuss weg


Betrachten Sie dies in einem beliebten Beispiel mit moment.js : import moment from 'moment' . Wenn Sie eine leere Anwendung nehmen, moment.js und ReactDOM importieren und dann über WebpackBundleAnalyzer übergeben , wird das folgende Bild angezeigt .

Bild

Es stellt sich heraus, dass Sie, wenn Sie einem Datum einen Tag, eine Stunde zu einem Datum hinzufügen oder einfach den Link "in 15 Minuten" mit moment.js setzen möchten, ganze 230 KB Code verbinden ! Warum passiert das und wie wird es gelöst?

Gebietsschema wird gerade geladen


In moment.js gibt es eine Funktion, die die Gebietsschemas festlegt:

 function setLocale(locale) { const localePath = 'locale/' + locale + '.js'; this._currentLocale = require(localePath); } 

Aus dem Code ist ersichtlich, dass das Gebietsschema entlang des dynamischen Pfads geladen wird, d. H. in Laufzeit berechnet. Webpack agiert intelligent und versucht sicherzustellen, dass Ihr Bundle während der Codeausführung nicht abstürzt: Es findet alle möglichen Gebietsschemas im Projekt und bündelt sie. Daher wiegt die Anwendung so viel.

Bild

Die Lösung ist sehr einfach: Wir nehmen ein Standard-Plugin aus Webpack und sagen dazu: "Wenn Sie sehen, dass jemand viele Gebietsschemas herunterladen möchte, weil er nicht bestimmen kann, welches, nehmen Sie einfach das russische!"

Bild

Webpack akzeptiert nur Russisch und WebpackBundleAnalyzer zeigt 54 KB an, was bereits 200 KB einfacher ist.

Eliminierung des toten Codes


Die nächste Optimierung, die uns interessiert, ist die Beseitigung von totem Code . Betrachten Sie den folgenden Code.

 const cond = true; if (!cond) { return false; } return true; someFunction(42); 

Die meisten Zeilen aus diesem Code werden im endgültigen Bundle nicht benötigt - der Block mit der Bedingung wird nicht ausgeführt, die Funktion auch nach der Rückgabe. Alles, was Sie verlassen müssen, ist die return true . Genau das ist die Beseitigung von totem Code: Das Build-Tool erkennt Code, der nicht ausgeführt werden kann, und schneidet ihn. Es gibt eine nette Funktion, mit der UglifyJS dies tun kann.

Fahren wir nun mit der fortgeschritteneren Methode zur Beseitigung von totem Code fort - der Baumschüttelmethode .

Baum zittern


Angenommen , wir haben eine Anwendung, die Lodash verwendet . Ich bezweifle stark, dass jemand das ganze Lodash benutzt. Höchstwahrscheinlich werden verschiedene Funktionen wie get , IsEmpty , unionBy oder dergleichen ausgenutzt .

Wenn wir Tree Shaking durchführen, möchten wir, dass Webpack die unnötigen Module „schüttelt“ und wegwirft, und wir haben nur die erforderlichen. Das ist Baumschütteln.

So funktioniert das Baumschütteln in Webpack


Angenommen, Sie haben einen Code wie diesen:

 import { a } from './a.js'; console.log(a); 

Der Code ist sehr einfach: Importieren Sie aus einem Modul die Variable a und geben Sie sie aus. In diesem Modul gibt es jedoch zwei Variablen: a und b . Wir brauchen die Variable b nicht und wollen sie entfernen.

 export const a = 3 export const b = 4 

Wenn Webpack eintrifft, konvertiert es den Importcode in Folgendes:

 var d = require(0); console.log(d["a"]); 

Unser import wurde require , aber console.log nicht geändert.

Die Webpack-Abhängigkeit wird in den folgenden Code konvertiert:

 var a = 3; module.exports["a«] = a; /* unused harmony export b */ var b = 4; 


Webpack hat den Export der Variablen a verlassen und den Export der Variablen b entfernt , aber die Variable selbst verlassen und sie mit einem speziellen Kommentar markiert. Im konvertierten Code wird die Variable b nicht verwendet, und UglifyJS kann sie löschen.

Das Schütteln des Webpack-Baums funktioniert nur, wenn Sie eine Art Code-Minifier wie UglifyJS oder babel-minify haben .

Betrachten wir interessantere Fälle - wenn das Baumschütteln nicht funktioniert.

Wenn Baumschütteln nicht funktioniert


Fall Nr. 1. Sie schreiben den Code:

 module.exports.a = 3; module.exports.b = 4; 

Führen Sie den Code über Webpack aus, und er bleibt unverändert. Dies liegt daran, dass der Bundler das Tree-Shaking nur organisiert, wenn Sie ES6-Module verwenden. Wenn Sie CommonJS-Module verwenden, funktioniert das Tree-Shaking nicht.

Fall Nr. 2. Sie schreiben Code mit ES6-Modulen und benannten Exporte.

 export const a = 3 export const b = 4 

Wenn Ihr Code Babel durchläuft und Sie die Moduloption nicht auf false gesetzt haben , bringt Babel Ihre Module zu CommonJS, und Webpack kann Tree Shaking erneut nicht ausführen, da es nur mit ES6-Modulen funktioniert.

 module.exports.a = 3; module.exports.b = 4; 

Dementsprechend müssen wir sicher sein, dass niemand in unserem Montageplan ES6-Module überträgt.

Fall Nr. 3. Angenommen, wir haben eine so nutzlose Klasse, die nichts tut: export class ShakeMe {} . Außerdem verwenden wir es immer noch nicht. Wenn Webpack importiert und exportiert wird, verwandelt Babel die Klasse in eine Funktion, und der Bundler stellt fest, dass die Funktion nicht verwendet wird:

 /* unused harmony e[port b */ var ShakeMe = function () { function ShakeMe() { babelHelpers.classCallCheck(this, ShakeMe); } return ShakeMe; }(); 

Es scheint, dass alles in Ordnung sein sollte, aber wenn wir genauer hinschauen, werden wir sehen, dass es in dieser Funktion eine globale Variable babelHelpers , von der eine Funktion aufgerufen wird. Dies ist ein Nebeneffekt : UglifyJS sieht, dass eine globale Funktion aufgerufen wird, und schneidet den Code nicht, da befürchtet wird, dass etwas kaputt geht.

Wenn Sie Klassen schreiben und sie durch Babel laufen lassen, werden sie nie geschnitten. Wie ist das behoben? Es gibt einen standardisierten Hack - fügen Sie vor der Funktion einen Kommentar /*#__PURE__*/ :

 /* unused harmony export b */ var ShakeMe = /*#__PURE__*/ function () { function ShakeMe() { babelHelpers.classCallCheck(this, ShakeMe); } return ShakeMe; }(); 

Dann wird UglifyJS an das Wort glauben, dass die nächste Funktion rein ist. Glücklicherweise macht Babel 7 dies jetzt und in Babel 6 wurde bisher nichts entfernt.

Regel: Wenn Sie irgendwo eine Nebenwirkung haben, wird UglifyJS nichts tun.

Zusammenfassend:

  • Das Schütteln von Bäumen funktioniert für die meisten Bibliotheken ab npm nicht , da sie alle von CommonJS stammen und vom alten Babel erstellt wurden.
  • Höchstwahrscheinlich funktioniert das Baumschütteln für diejenigen Bibliotheken, die bereits darauf vorbereitet sind , z. B. Lodash-es, Date-fns und Ihren Code oder Ihre Bibliotheken, angemessen.
  • UglifyJS ist an der Montage beteiligt.
  • Gebrauchte ES6-Module.
  • Keine Nebenwirkungen.

Wir haben herausgefunden, wie Sie das Gewicht des Bundles reduzieren können, und jetzt lernen wir, nur die erforderlichen Funktionen zu laden.

Wir laden nur die notwendigen Funktionen


Wir teilen diesen Teil in zwei Teile. Im ersten Teil wird nur der Code geladen, den der Benutzer benötigt : Wenn der Benutzer die Hauptseite Ihrer Website besucht, lädt er die persönlichen Kontoseiten nicht. Im zweiten Fall führen Änderungen im Code zu einem möglichst geringen Nachladen von Ressourcen .

Wir laden nur den notwendigen Code


Betrachten Sie die Struktur einer imaginären Anwendung. Es hat:

  • Einstiegspunkt - APP.
  • Drei Seiten: Home, Suche und Karte.

Bild

Das erste Problem, das wir lösen möchten, ist die Ausgabe eines gemeinsamen Codes . Bezeichnen wir den roten Code als gemeinsamen Code für alle Seiten, den grünen Kreis für die Hauptseite und die Suchseite. Die übrigen Zahlen sind nicht besonders wichtig.

Bild

Wenn der Benutzer von der Hauptseite zur Suche kommt, lädt er die Box und den Kreis ein zweites Mal neu, obwohl er sie bereits hat. Im Idealfall möchten wir so etwas sehen.

Bild

Es ist gut, dass Webpack 4 bereits ein integriertes Plugin hat, das dies für uns erledigt - SplitChunksPlugin . Das Plugin entfernt den Anwendungscode oder den Knotenmodulcode, der von mehreren Blöcken in einem separaten Block verwendet wird, wobei sichergestellt wird, dass der Block mit dem allgemeinen Code mehr als 30 KB groß ist. Um die Seite zu laden, müssen Sie nicht mehr als 5 Blöcke herunterladen. Die Strategie ist optimal: Das Laden zu kleiner Chunks ist nicht rentabel, und das Laden zu vieler Chunks ist lang und nicht so effizient wie das Herunterladen weniger Chunks, selbst auf http2. Um dieses Verhalten in 2 oder 3 Versionen von Webpack zu wiederholen, musste ich 20 bis 30 Zeilen mit undokumentierten Funktionen schreiben. Jetzt wird dies in einer Zeile gelöst.

CSS zum Mitnehmen


Es wäre großartig, wenn wir das CSS für jeden Block noch in einer separaten Datei herausnehmen würden. Hierfür gibt es eine fertige Lösung - das Mini-Css-Extract-Plugin . Das Plugin erschien nur in Webpack 4, und davor gab es keine adäquaten Lösungen für eine solche Aufgabe - nur Hacks, Schmerzen und Schussbeine. Das Plugin entfernt CSS aus asynchronen Chunks und wurde speziell für diese Aufgabe erstellt , die es perfekt ausführt.

Minimal mögliches erneutes Laden von Ressourcen


Wir werden herausfinden, wie Sie sicherstellen können, dass der Benutzer beim Freigeben eines neuen Werbeblocks auf der Hauptseite den kleinstmöglichen Teil des Codes neu lädt .

Wenn wir eine Versionierung hätten, wäre alles in Ordnung. Hier haben wir die Hauptseite von Version N und nach der Veröffentlichung des Promo-Blocks - Version N + 1. Webpack bietet einen ähnlichen Mechanismus sofort mit Hashing. Nachdem Webpack alle Assets gesammelt hat, in diesem Fall app.js, berechnet es seinen Inhalts-Hash und fügt ihn dem Dateinamen hinzu, um app. [Hash] .js zu erhalten. Dies ist die Versionierung, die wir brauchen.

Bild

Lassen Sie uns überprüfen, wie es funktioniert. Aktivieren Sie die Hashes, nehmen Sie Änderungen auf der Hauptseite vor und prüfen Sie, ob sich der Code der Hauptseite wirklich geändert hat. Wir werden feststellen, dass sich zwei Dateien geändert haben: main und app.js.

Bild

Warum ist das passiert, weil es unlogisch ist? Um zu verstehen, warum, werfen wir einen Blick auf app.js. Es besteht aus drei Teilen:

  • Anwendungscode
  • Webpack-Laufzeit;
  • Links zu asynchronen Chunks.

Wenn wir den Code in main ändern, ändern sich Inhalt und Hash, was bedeutet, dass sich der Link dazu auch in der App ändert. Die App selbst ändert sich ebenfalls und muss neu gestartet werden. Die Lösung für dieses Problem besteht darin , app.js in zwei Blöcke aufzuteilen: Anwendungscode und Webpack-Laufzeit sowie Links zu asynchronen Blöcken. Webpack 4 erledigt alles für uns mit einer runtimeChunk- Option, die sehr wenig wiegt - weniger als 2 KB in gzip. Ein Neustart für den Benutzer ist praktisch wertlos. RuntimeChunk wird mit nur einer Option aktiviert:

 optimization: { runtimeChunk: true } 

In Webpack 3 und 2 würden wir 5-6 Zeilen anstelle von einer schreiben. Dies ist nicht viel mehr, aber immer noch eine zusätzliche Unannehmlichkeit.

Bild

Alles ist großartig, wir haben gelernt, Links und Laufzeit zu erstellen! Schreiben wir ein neues Modul in main, geben es frei und - op! - Jetzt wird im Allgemeinen alles neu gestartet.

Bild

Warum so? Mal sehen, wie Module im Webpack funktionieren.

Webpack-Module


Angenommen, es gibt Code, in dem Sie die Module a , b , d und e hinzufügen:

 import a from 'a'; import b from 'b'; import d from 'd'; import e from 'e'; 

Webpack konvertiert Importe nach Bedarf: a , b , d und e werden durch erfordern (0), erfordern (1), erfordern (2) und erfordern (3) ersetzt.

 var a = require(0); var b = require(1); var d = require(2); var e = require(3); 

Stellen Sie sich ein Bild vor, das sehr häufig vorkommt: Sie schreiben ein neues Modul c import c from 'c'; und füge es irgendwo in der Mitte ein:

 import a from 'a'; import b from 'b'; import c from 'c'; import d from 'd'; import e from 'e'; 

Wenn Webpack alles verarbeitet, konvertiert es den Import des neuen Moduls in require (2):

 var a = require(0); var b = require(1); var c = require(2); var d = require(3); var e = require(4); 

Die Module d und e , die 2 und 3 waren, erhalten die Nummern 3 und 4 - die neue ID. Daraus folgt eine einfache Schlussfolgerung: Die Verwendung von Seriennummern als ID ist etwas albern, aber Webpack tut es.

Verwenden Sie keine Seriennummer als eindeutige ID

Um das Problem zu beheben, gibt es eine integrierte Webpack-Lösung - HashedModuleIdsPlugin :

 new webpack.HashedModuleIdsPlugin({ hashFunction: 'md4′, hashDigest:'base64′, hashDigestLength: 4, }), 

Dieses Plugin verwendet 4 Zeichen md4-Hash anstelle der digitalen ID vom absoluten Pfad zur Datei. Damit wird unser Bedarf in folgende umgewandelt:

 var a = require('YmRl'); var b = require('N2Fl'); var c = require('OWE4′); var d = require('NWQz'); var e = require('YWVj'); 

Anstelle von Zahlen erschienen Buchstaben. Natürlich gibt es ein verstecktes Problem - dies ist eine Kollision von Hashes . Wir sind einmal darauf gestoßen und können Ihnen raten, 8 statt 4 Zeichen zu verwenden. Nachdem Sie die Hashes richtig konfiguriert haben, funktioniert alles so, wie wir es ursprünglich wollten.

Wir wissen jetzt, wie man Traumbündel sammelt.

  • Minimieren .
  • Verwenden Sie die Codeaufteilung .
  • Hashes einrichten .

Wir haben das Sammeln gelernt und jetzt werden wir an der Geschwindigkeit arbeiten.

Wie kann man schnell ein Traumbündel zusammenstellen?


In unserer N1.RU besteht die größte Anwendung aus 10.000 Modulen und ohne Optimierungen dauert es 28 Minuten. Wir konnten die Montage auf zwei Minuten beschleunigen! Wie haben wir das gemacht? Es gibt drei Möglichkeiten, um Berechnungen zu beschleunigen, und alle drei gelten für Webpack.

Baugruppenparallelisierung


Als erstes haben wir die Montage parallelisiert . Dafür haben wir:

  • HappyPackPlugin , das Ihre Lader in andere Lader einwickelt und alle Berechnungen, die in separate Prozesse verpackt sind, übernimmt. Dies ermöglicht beispielsweise die Parallelisierung von Babel und Node-Sass.
  • Fadenlader . Funktioniert ungefähr genauso wie HappyPackPlugin, verwendet nur keine Prozesse, sondern einen Thread-Pool. Das Wechseln zu einem separaten Thread ist eine kostspielige Operation. Gehen Sie vorsichtig damit um und nur dann, wenn Sie ressourcenintensive und schwere Operationen wie babel oder node-sass abschließen möchten. Zum Laden von json ist beispielsweise keine Parallelisierung erforderlich, da diese schnell geladen wird.
  • Die Plugins und Loader, die Sie höchstwahrscheinlich verwenden, verfügen bereits über integrierte Parallelisierungstools - Sie müssen nur schauen. Diese Option befindet sich beispielsweise in UglifyJS .

Caching-Build-Ergebnisse


Das Zwischenspeichern von Assembly-Ergebnissen ist der effizienteste Weg, um die Webpack-Assembly zu beschleunigen.

Die erste Lösung ist der Cache-Loader . Dies ist ein Loader, der in eine Loaderkette gerät und das Ergebnis des Erstellens einer bestimmten Datei für eine bestimmte Loaderkette im Dateisystem speichert. Wenn sich diese Datei beim nächsten Zusammenbau des Bundles im Dateisystem befindet und bereits mit dieser Kette verarbeitet wurde, übernimmt der Cache-Loader die Ergebnisse und ruft nicht die dahinter liegenden Loader auf, z. B. Babel-Loader oder Node-Sass.

Die Grafik zeigt die Montagezeit. Blauer Balken - 100% Bauzeit, ohne Cache-Loader und damit - 7% langsamer. Dies liegt daran, dass der Cache-Loader zusätzliche Zeit damit verbringt, Caches im Dateisystem zu sparen. Bereits bei der zweiten Montage haben wir einen spürbaren Gewinn erzielt - die Montage war zweimal schneller.

Bild

Die zweite Lösung ist anspruchsvoller - HardSourcePlugin . Der Hauptunterschied: Cache-Loader ist nur ein Loader, der nur in einer Kette von Loadern mit Code oder Dateien ausgeführt werden kann. HardSourcePlugin hat fast vollständigen Zugriff auf das Webpack-Ökosystem, kann mit anderen Plugins und Loadern betrieben werden und erweitert das Ökosystem für das Caching ein wenig. Die obige Grafik zeigt, dass sich die Erstellungszeit beim ersten Start um 37% erhöhte, beim zweiten Start mit allen Caches jedoch um das Fünffache.

Bild

Das Beste daran ist, dass Sie beide Lösungen zusammen verwenden können, was wir bei N1.RU tun. Seien Sie vorsichtig, da es Probleme mit Caches gibt, auf die ich später noch eingehen werde.

Die Plugins / Loader, die Sie bereits verwenden, verfügen möglicherweise über integrierte Caching-Mechanismen . Zum Beispiel hat Babel-Loader ein sehr effizientes Caching-System, das jedoch aus irgendeinem Grund standardmäßig deaktiviert ist. Die gleiche Funktionalität ist in awesome-typeScript-loader . Das UglifyJS- Plugin verfügt auch über Caching, was hervorragend funktioniert. Er hat uns um einige Minuten beschleunigt.

Und jetzt die Probleme.

Caching-Probleme


  • Der Cache wird möglicherweise nicht korrekt überprüft .
  • Angewandte Lösungen funktionieren möglicherweise nicht mit verbundenen Plugins, Loadern, Ihrem Code oder untereinander . In dieser Hinsicht ist der Cache-Loader eine einfache und problemlose Lösung. Bei HardSourcePlugin müssen Sie jedoch vorsichtiger sein.
  • Es ist schwer zu debütieren, wenn alles kaputt ist . Wenn das Caching nicht richtig funktioniert und ein unverständlicher Fehler auftritt, ist es sehr schwierig, das Problem herauszufinden.

Wie kann man bei der Produktion sparen?


Die letzte Möglichkeit, einen Prozess zu beschleunigen, besteht darin, keinen Teil des Prozesses auszuführen. Lassen Sie uns darüber nachdenken, wie Sie bei der Produktion sparen können. Was können wir nicht tun? Die Antwort ist kurz - wir können nichts tun ! Wir haben kein Recht, etwas in der Produktion abzulehnen, aber wir können viel in der Entwicklung sparen.

Was Sie sparen sollten:

  • Sammeln Sie die Quellkarte erst, wenn wir sie brauchen.
  • Verwenden Sie Style-Loader anstelle eines coolen Schemas mit CSS-Entfernung und -Verarbeitung über CSS-Loader. Der Style-Loader selbst ist sehr schnell, da er die CSS-Zeile in eine Funktion schiebt, die diese Zeile in das Style-Tag einfügt.
  • Sie können in der Browserliste nur den Browser belassen, den Sie speziell verwenden - höchstwahrscheinlich ist dies das letzte Chrom . Dies wird sich stark beschleunigen .
  • Geben Sie die Optimierung von Ressourcen vollständig auf : von UglifyJS, css-nano, gzip / brotli.

Build-Beschleunigung ist Parallelisierung, Caching und Ablehnung von Berechnungen. Wenn Sie diese drei einfachen Schritte ausführen, können Sie sehr stark beschleunigen.

Wie konfiguriere ich das Webpack?


Wir haben herausgefunden, wie man ein Traumbündel zusammenbaut und wie man es schnell zusammenbaut, und jetzt werden wir herausfinden, wie man Webpack so konfiguriert, dass wir uns nicht jedes Mal ins Bein schießen, wenn Sie die Konfiguration ändern.

Konfigurationsentwicklung im Projekt


Ein typischer Webpack-Konfigurationspfad in einem Projekt beginnt mit einer einfachen Konfiguration. Zuerst fügen Sie einfach Webpack, Babel-Loader, Sass-Loader ein und alles ist gut. Dann werden unerwartet einige Bedingungen in process.env angezeigt , und Sie fügen die Bedingungen ein. Eins, zwei, drei, immer mehr, bis eine Bedingung mit einer "magischen" Option hinzugefügt wird. Sie verstehen, dass bereits alles ziemlich schlecht ist, und es ist besser, nur die Konfigurationen für Entwickler und Produktion zu duplizieren und zweimal Korrekturen vorzunehmen. Alles wird klarer. Wenn Sie einen Gedanken hatten: "Stimmt hier etwas nicht?", Dann ist der einzige funktionierende Rat , die Konfiguration in Ordnung zu halten . Ich werde Ihnen sagen, wie wir es machen.

Halten Sie die Konfiguration in Ordnung


Wir verwenden das Webpack-Merge- Paket. Dies ist ein npm-Paket, das erstellt wurde, um mehrere Konfigurationen zu einer zu kombinieren. Wenn Sie mit der Standard-Zusammenführungsstrategie nicht vertraut sind, können Sie sie anpassen.


4 :

  • Loaders.
  • Plugins.
  • Presets.
  • Parts.

.

Plugin/Loader


, , API, , .

Es sieht ungefähr so ​​aus:

 /** *  JSdoc * @param {Object} options * @see    */ module.exports = function createPlugin(options) { return new Plugin(options); }; 

, , , . , url-loader :

 /** * url-loader    file-loader.        * * @example * -   some-image.png.     url-loader,  url-loader    * 1.    ,  url-loader    base64  * 2. , url-loader    outputPath + name     ,     . *    some-image.png,     outputPath/images/some-image.12345678hash.png,  url-loader  * publicPath/images/some-image.12345678hash.png * * @param {string} prefix    * @param {number} limit    ,    * @return {Object} loader   * @see https://www.npmjs.com/package/url-loader */ 

, , , , , , . , , , , url-loader. :

 function urlLoader(prefix = 'assets', limit = 100) { return { loader: 'url-loader', options: { limit, name: `${prefix}/[name].[hash].[ext]` } }; }; 

. , Loader .

Preset


webpack. , , , webpack, . — , , scss-:

 { test: /\.scss$/, use: [cssLoader, postCssLoader, scssLoader] } 

.

Part


— , . , , . , :

 entry: { app: './src/Frontend/app.js' }, output: { publicPath: '/static/cabinet/app/', path: path.resolve('www/static/app') }, 

:

  • , , , json, , , splitChunks.
  • dev , , js/css
  • Part , output, publicPath, entry-point , , source map.

Bild

Webpack-merge . , . webpack-merge 3-7 , Babel-loader, . , .


Zusammenfassend. , . , webpack — . , .

, !

Frontend Conf . , — , , Frontend Conf ++ .

- ? FrontenConf ++ , 27 28 . 27 , 15 . — !

Source: https://habr.com/ru/post/de433324/


All Articles