Was genau ist Hot Module Replacement in Webpack?

245

Ich habe einige Seiten über das Ersetzen von Hot-Modulen in Webpack gelesen.
Es gibt sogar eine Beispiel-App , die es verwendet .

Ich habe das alles gelesen und komme immer noch nicht auf die Idee.

Was kann ich damit machen?

  1. Soll es nur in der Entwicklung und nicht in der Produktion verwendet werden?
  2. Ist es wie LiveReload, aber Sie müssen es selbst verwalten?
  3. Ist WebpackDevServer in irgendeiner Weise in LiveReload integriert?

Angenommen, ich möchte meine CSS- (ein Stylesheet-) und JS-Module aktualisieren, wenn ich sie auf der Festplatte speichere, ohne die Seite neu zu laden und ohne Plugins wie LiveReload zu verwenden. Kann mir Hot Module Replacement dabei helfen? Welche Art von Arbeit muss ich tun und was bietet HMR bereits an?

Dan Abramov
quelle
HMR mit Webpack ist fast so gut wie das: medium.com/@the1mills/…
Alexander Mills

Antworten:

406

Zunächst möchte ich darauf hinweisen, dass der Hot Module Replacement (HMR) immer noch eine experimentelle Funktion ist.

HMR ist eine Möglichkeit, Module in einer laufenden Anwendung auszutauschen (und Module hinzuzufügen / zu entfernen). Grundsätzlich können Sie geänderte Module ohne erneutes Laden der gesamten Seite aktualisieren.

Dokumentation

Voraussetzungen:

Es ist nicht so sehr für HMR, aber hier sind die Links:

Ich werde diese Antworten zur Dokumentation hinzufügen.

Wie funktioniert es?

Aus der App-Ansicht

Der App-Code fordert die HMR-Laufzeit auf, nach Updates zu suchen. Die HMR-Laufzeit lädt die Updates herunter (asynchron) und teilt dem App-Code mit, dass ein Update verfügbar ist. Der App-Code fordert die HMR-Laufzeit auf, Aktualisierungen anzuwenden. Die HMR-Laufzeit wendet die Aktualisierungen an (Synchronisierung). Der App-Code erfordert möglicherweise eine Benutzerinteraktion in diesem Prozess (Sie entscheiden).

In der Compiler-Ansicht (Webpack)

Zusätzlich zu den normalen Assets muss der Compiler das "Update" ausgeben, um ein Update von einer früheren Version auf diese Version zu ermöglichen. Das "Update" besteht aus zwei Teilen:

  1. das Update-Manifest (json)
  2. ein oder mehrere Update-Chunks (js)

Das Manifest enthält den neuen Kompilierungs-Hash und eine Liste aller Update-Chunks (2).

Die Aktualisierungsblöcke enthalten Code für alle aktualisierten Module in diesem Block (oder ein Flag, wenn ein Modul entfernt wurde).

Der Compiler stellt außerdem sicher, dass die Modul- und Chunk-IDs zwischen diesen Builds konsistent sind. Es verwendet eine json-Datei "records", um sie zwischen Builds zu speichern (oder speichert sie im Speicher).

Aus der Modulansicht

HMR ist eine Opt-In-Funktion und betrifft daher nur Module, die HMR-Code enthalten. In der Dokumentation wird die API beschrieben, die in Modulen verfügbar ist. Im Allgemeinen schreibt der Modulentwickler Handler, die aufgerufen werden, wenn eine Abhängigkeit dieses Moduls aktualisiert wird. Sie können auch einen Handler schreiben, der aufgerufen wird, wenn dieses Modul aktualisiert wird.

In den meisten Fällen muss nicht in jedem Modul HMR-Code geschrieben werden. Wenn ein Modul keine HMR-Handler hat, sprudelt das Update. Dies bedeutet, dass ein einzelner Handler Aktualisierungen für einen vollständigen Modulbaum verarbeiten kann. Wenn ein einzelnes Modul in diesem Baum aktualisiert wird, wird der gesamte Modulbaum neu geladen (nur neu geladen, nicht übertragen).

Aus der HMR-Laufzeitansicht (technisch)

Zusatzcode ist für die Modul Systemlaufzeit ausgesendeten Modul zu verfolgen parentsund children.

Auf der Verwaltungsseite unterstützt die Laufzeit zwei Methoden: checkund apply.

A checkführt eine HTTP-Anforderung an das Aktualisierungsmanifest durch. Wenn diese Anforderung fehlschlägt, ist kein Update verfügbar. Andernfalls wird die Liste der aktualisierten Chunks mit der Liste der aktuell geladenen Chunks verglichen. Für jeden geladenen Block wird der entsprechende Update-Block heruntergeladen. Alle Modulaktualisierungen werden zur Laufzeit als Aktualisierungen gespeichert. Die Laufzeit wechselt in den readyStatus, dh ein Update wurde heruntergeladen und kann angewendet werden.

Für jede neue Blockanforderung im Bereitschaftszustand wird auch der Aktualisierungsblock heruntergeladen.

Die applyMethode kennzeichnet alle aktualisierten Module als ungültig. Für jedes ungültige Modul muss ein Update-Handler im Modul oder Update-Handler in jedem übergeordneten Modul vorhanden sein. Andernfalls sprudelt das Ungültige und markiert auch alle Eltern als ungültig. Dieser Vorgang wird fortgesetzt, bis kein "Aufblasen" mehr auftritt. Wenn es bis zu einem Einstiegspunkt sprudelt, schlägt der Prozess fehl.

Jetzt werden alle ungültigen Module entsorgt (Entsorgungshandler) und entladen. Dann wird der aktuelle Hash aktualisiert und alle "Accept" -Handler werden aufgerufen. Die Laufzeit wechselt wieder in den idleZustand und alles läuft normal weiter.

generierte Update-Chunks

Was kann ich damit machen?

Sie können es in der Entwicklung als LiveReload-Ersatz verwenden. Tatsächlich unterstützt der Webpack-Dev-Server einen Hot-Modus, der versucht, mit HMR zu aktualisieren, bevor versucht wird, die gesamte Seite neu zu laden. Sie müssen nur den webpack/hot/dev-serverEinstiegspunkt hinzufügen und den Dev-Server mit aufrufen --hot.

Sie können es auch in der Produktion als Aktualisierungsmechanismen verwenden. Hier müssen Sie Ihren eigenen Verwaltungscode schreiben, der HMR in Ihre App integriert.

Einige Lader generieren bereits Module, die im laufenden Betrieb aktualisiert werden können. zB Die style-loaderkönnen das Stylesheet austauschen. Sie müssen nichts Besonderes tun.

Angenommen, ich möchte meine CSS- (ein Stylesheet-) und JS-Module aktualisieren, wenn ich sie auf der Festplatte speichere, ohne die Seite neu zu laden und ohne Plugins wie LiveReload zu verwenden. Kann mir Hot Module Replacement dabei helfen?

Ja

Welche Art von Arbeit muss ich tun und was bietet HMR bereits an?

Hier ein kleines Beispiel: https://webpack.js.org/guides/hot-module-replacement/

Ein Modul kann nur aktualisiert werden, wenn Sie es "akzeptieren". Sie müssen also module.hot.acceptdas Modul in den Eltern oder den Eltern der Eltern ... zB Ein Router ist ein guter Ort oder eine Unteransicht.

Wenn Sie es nur mit dem Webpack-Dev-Server verwenden möchten, fügen Sie es einfach webpack/hot/dev-serverals Einstiegspunkt hinzu. Andernfalls benötigen Sie einen HMR-Verwaltungscode, der checkund aufruft apply.

Meinung: Was macht es so cool?

  • Es ist LiveReload, aber für jede Modulart.
  • Sie können es in der Produktion verwenden.
  • Die Updates berücksichtigen Ihre Code-Aufteilung und laden nur Updates für die verwendeten Teile Ihrer App herunter.
  • Sie können es für einen Teil Ihrer Anwendung verwenden und es wirkt sich nicht auf andere Module aus
  • Wenn HMR deaktiviert ist, wird der gesamte HMR-Code vom Compiler entfernt (einpacken if(module.hot)).

Vorsichtsmaßnahmen

  • Es ist experimentell und nicht so gut getestet.
  • Erwarten Sie einige Fehler.
  • Theoretisch in der Produktion verwendbar, aber es kann zu früh sein, um es für etwas Ernstes zu verwenden.
  • Die Modul-IDs müssen zwischen den Kompilierungen verfolgt werden, damit Sie sie speichern können ( records).
  • Der Optimierer kann die Modul-IDs nach der ersten Kompilierung nicht mehr optimieren. Ein kleiner Einfluss auf die Bundle-Größe.
  • HMR-Laufzeitcode erhöht die Bundle-Größe.
  • Für den Produktionseinsatz sind zusätzliche Tests erforderlich, um die HMR-Handler zu testen. Das könnte ziemlich schwierig sein.
Tobias K.
quelle
145
Eine verdammt gute Antwort.
Dan Abramov
13
Nochmals vielen Dank für die Erklärung. Ich habe ein Video erstellt, in dem die Leistungsfähigkeit von HMR für die Live-Bearbeitung einer React-App gezeigt wird.
Dan Abramov
1
ziemlich cool ... Ich dachte darüber nach, einen React Loader zu entwickeln, der HMR und asynchrones Laden hinzufügt, um Komponenten zu reagieren.
Tobias K.
4
Ich habe diese Antwort in die Dokumentation kopiert: webpack.github.io/docs/hot-module-replacement-with-webpack.html
Tobias K.
2
Sie können Fehler in aktualisierten Modulen abfangen, wenn Sie requireden HMR-Update-Handler in einen Try-Catch-Block einschließen.
Tobias K.
10

Die akzeptierte Antwort erklärt sowieso alles richtig. Die folgende Beschreibung hilft, schnell zu verstehen, was HMR ist.

Der Austausch von Hot-Modulen ist eine der neuesten Techniken in der Javascript-Entwicklung, die die Aufmerksamkeit der Entwickler auf sich zieht. Es unterstützt die Entwicklung, indem es die Anzahl der Seitenaktualisierungen reduziert, indem die Module zur Laufzeit durch Änderungen ersetzt werden.

Bei der Suche nach HMR habe ich einen Artikel gefunden , der das Konzept im Internet erklärt. Sie können ihn hier herunterladen und ein GIF-Bild hinzufügen, das das Konzept ohne viel Erklärung erklärt.

Hier ist es am Werk - beachten Sie, dass der Timer nicht wie nach einem erneuten Laden der Seite auf 0 zurückgesetzt wird und CSS auch die automatische Aktualisierung ändert. Hot Module Ersatz GIF

Webpack hilft, HMR zu erreichen. Dokumente finden Sie hier

Es hilft, folgendes zu erreichen

  • Behalten Sie den Anwendungsstatus bei, der beim vollständigen Neuladen verloren geht.

  • Sparen Sie wertvolle Entwicklungszeit, indem Sie nur die Änderungen aktualisieren.

  • Schnelleres Styling - fast vergleichbar mit dem Ändern von Styles im Debugger des Browsers.

Hier ist der Webpack-Leitfaden, um HMR zu erreichen

samuelj90
quelle