Eigenständiges HTML aus Chrome für den Import exportieren

Chromes Menü Speichern unter bietet drei Exportmodi, aber nur einer kommt einer wirklich eigenständigen HTML-Datei nahe. So findest du den richtigen.

TUTORIALDEVELOPERVeröffentlicht

Chromes drei Speichern-unter-Optionen, und warum nur eine wirklich nahekommt

Drücke Strg+S (Cmd+S auf dem Mac) auf einer beliebigen Seite in Chrome, und du bekommst drei Optionen: Webseite, komplett; Webseite, nur HTML; und MHTML, einzelne Datei. Wenn dein Ziel ist, HTML aus Chrome als eine einzige portable Datei für ein Import-Tool zu exportieren, ist nur einer dieser drei Namen ehrlich darüber, was er tatsächlich erzeugt, und es ist wahrscheinlich nicht der, den du vermutest.

Webseite, komplett schreibt das Markup in eine .html-Datei und legt jedes Bild, jedes Stylesheet und jedes Skript der Seite in einen zugehörigen Ordner _files daneben. Die beiden Teile müssen zusammen bleiben. Verschiebst du die .html-Datei allein, bricht jeder relative Verweis auf den Ordner. Das scheidet als einzelne eigenständige Datei aus. Es ist außerdem die Option, die die meisten standardmäßig wählen, weil sie als Erste im Dropdown steht.

Webseite, nur HTML schreibt nur das Markup, ganz ohne _files-Ordner. Es ist die kleinste der drei Optionen, und hier die am wenigsten nützliche: Jeder Verweis auf eine externe Ressource bleibt in der Datei bestehen und zeigt auf Bilder und Stylesheets, die nicht mehr angehängt sind. Öffnest du sie später, bekommst du nackten Text, wo vorher die Seite war.

MHTML wirkt eigenständig. Es ist kein reines HTML

MHTML, einzelne Datei erzeugt eine Datei mit allem darin, weshalb es verlockend ist, sie für die Lösung zu halten. Unter der Oberfläche ist sie aber kein reines HTML. MHTML verpackt die Seite in MIME-Multipart/related-Kodierung, dieselbe Technik, die Browser für HTML-E-Mail-Anhänge verwenden: ein E-Mail-artiger Header mit Titel, Quell-URL und Zeitstempel, gefolgt vom HTML und dann jeder Ressource, base64-kodiert und durch Grenzzeichenfolgen getrennt. Chrome 86 und neuer schreibt dieses Format über Speichern unter. Dieselbe Ausgabe steht auch programmgesteuert über die saveAsMHTML-Methode der pageCapture-Erweiterungs-API zur Verfügung, die die meisten automatischen Capture-Erweiterungen aufrufen, statt das Format selbst neu zu implementieren. Eine Einschränkung, die man kennen sollte: Die entstandene Datei lässt sich nur vom lokalen Dateisystem öffnen, und nur im Hauptframe eines Browsers, niemals in einem iframe.

Warum MHTML nicht das eigenständige HTML ist, das ein Importer braucht

Ein Tool, das reines HTML parst, einschließlich der Dropzone von UnHTML, liest eine .html-Datei als HTML: Tags, Attribute, ein DOM. Eine .mhtml-Datei ist das nicht. Sie ist ein MIME-Container mit einem HTML-Teil, der in base64-codierten Grenzen vergraben ist, und ein reiner HTML-Parser wird sie nicht korrekt entpacken. Ziehst du eine .mhtml-Datei in einen Importer, der eigenständiges HTML erwartet, bekommst du bestenfalls nichts Lesbares.

Es gibt noch eine zweite Lücke, die man kennen sollte, selbst wenn man nie auf das Dateiformat-Problem stößt. Eingebettetes JavaScript wird nicht ausgeführt, wenn eine MHTML-Datei erneut geöffnet wird; nur das HTML, das zum Zeitpunkt der Aufnahme bereits gerendert war, bleibt erhalten. Bei einer überwiegend statischen Seite spielt das selten eine Rolle. Bei allem, was einen Teil seines Layouts erst nach dem Laden aufbaut, fehlt in der Aufnahme alles, was nach dem Schnappschuss noch gelaufen ist.

Hast du schon eine .mhtml-Datei und brauchst daraus reines HTML, öffne sie erneut in Chrome und speichere sie mit einer echten Single-File-Erweiterung neu ab. Versuche nicht, den MIME-Container von Hand zu bearbeiten. Firefox liest MHTML überhaupt nicht nativ, eine auf einem Rechner gespeicherte .mhtml-Datei ist also auch nichts, was du einem Kollegen mit einem anderen Browser bedenkenlos weitergeben kannst.

Eine echte Single-File-HTML mit allem eingebettet erstellen

Eine wirklich eigenständige HTML-Datei bettet ihr CSS und ihre Bilder direkt ins Markup ein, meist als base64-Daten-URIs, sodass die einzelne Datei keine externen Verweise mehr hat, die brechen könnten. Chrome macht das nicht nativ. Es gibt kein DevTools-Panel und keine Speichern-unter-Option, die eine Seite durchgeht und jedes <img src> und <link rel="stylesheet"> in eine eingebettete Daten-URI umschreibt; dieser Umwandlungsschritt gehört einer Capture-Erweiterung von Drittanbietern.

Die Schritte, der Reihe nach:

  1. Lade die Seite vollständig in Chrome und scrolle einmal durch, damit alle verzögert ladenden Bilder und Abschnitte vor der Aufnahme ins DOM gerendert werden. Überspringst du das, fehlt in deiner Aufnahme, was noch nicht geladen war.
  2. Führe eine Single-File-Capture-Erweiterung aus, die CSS und Bilder als Daten-URIs einbettet, anstelle von Chromes nativem Speichern unter. Die meisten dieser Erweiterungen fügen eine Symbolleistenschaltfläche hinzu, die die Aufnahme im aktiven Tab auslöst, ganz ohne separate Anwendung.
  3. Speichere das Ergebnis als eine einzelne .html-Datei, mit einem Namen, der noch sinnvoll ist, wenn er in einem Downloads-Ordner neben einem Dutzend anderer liegt.
  4. Öffne diese Datei direkt von der Festplatte, nicht über einen lokalen Server, und überprüfe, dass jedes Bild und jeder Stil ohne gebrochene Verweise, ohne Netzwerkaktivität im Tab und ohne jede Verbindung zur Originaldomain gerendert wird. Eine Aufnahme, die noch die Live-Seite kontaktiert, ist nicht wirklich eigenständig.

Ein ehrlicher Kompromiss: Base64-Kodierung fügt dem, was sie umschließt, etwa 33 Prozent mehr Größe hinzu, sodass eine eingebettete Single-File-Exportdatei zuverlässig größer ausfällt als die Summe der ursprünglichen, getrennten Ressourcen der Seite. Ein 200-KB-Hero-Bild wird zu fast 266 KB, sobald es als base64-Text in der HTML steckt. Eine Handvoll großer Fotos kann eine Seite auf diese Weise in eine mehrere Megabyte große Datei verwandeln. Das ist der Preis echter Portabilität, kein Fehler im Prozess, und man sollte es kennen, bevor einen eine Dateigröße auf dem Weg in einen Importer überrascht.

Was eine statische Aufnahme behält, und was sie verliert

Ein Single-File-Export, ob MHTML oder eingebettetes HTML, friert das DOM zum Zeitpunkt der Aufnahme ein. Alles, was schon gerendert war, bleibt erhalten: Text, Layout, bereits geladene Bilder, bereits angewendete Stile. Alles, was nach diesem Moment passiert, bleibt nicht erhalten, weil kein Skript der Seite erneut läuft, wenn die Datei offline wieder geöffnet wird.

Dieser Unterschied zählt vor allem bei Seiten, die auf clientseitigem Verhalten aufbauen: Inhalte, die beim Scrollen nachladen, Daten, die über einen verzögerten Fetch ankommen, oder Ansichten, die sich mit clientseitigem Routing ändern. Nimm einen Endlos-Scroll-Feed als Beispiel. Eine statische Aufnahme hat nur die Handvoll Elemente, die beim Speichern schon geladen waren, nicht den Rest des Feeds, den ein Besucher durch weiteres Scrollen erreichen würde. Eine überwiegend statische Marketingseite oder ein Dokumentationsartikel kommt mit einem einfachen Speichern unter gut zurecht; es erfasst alles, was zählt. Eine JavaScript-lastige Single-Page-App ist eine andere Geschichte, und ein Capture-Tool, das eine echte Browser-Sitzung steuert und abwartet, bis sich die Netzwerkaktivität beruhigt, bevor es den Schnappschuss macht, ist hier die bessere Wahl.

Wenn Speichern unter nicht reicht

Zwei Wege existieren außerhalb von Chromes eigenem Exportmenü, und beide lohnt es sich zu kennen, bevor man annimmt, dass ein Speichern unter im Browser der einzige Einstiegspunkt ist.

Safari-Nutzer haben eine vierte Option, die Chrome nicht hat: das Format .webarchive. Es bündelt das HTML mit verknüpftem CSS, Bildern und JavaScript in einer von Apples binären Property-List-Dateien, nativ lesbar nur in Safari und mit einer anderen Kodierung gebaut als MHTMLs MIME-Container. UnHTML akzeptiert .webarchive-Dateien direkt als Alternative zu eigenständigem HTML, der praktischere Weg, wenn du ohnehin auf einem Mac arbeitest und lieber keine Capture-Erweiterung installieren möchtest. Siehe eine Seite als Safari Web Archive speichern für die vollständige Anleitung, einschließlich wo macOS die Datei standardmäßig ablegt.

Bei einer Live-Website oder allem, was sein Layout erst nach dem Laden mit JavaScript aufbaut, überspringe den Speichern-unter-Dialog des Browsers ganz. Nutze stattdessen die quelloffene Capture-CLI oder das Bookmarklet. Es steuert die Seite so, wie ein echter Besuch es täte, wartet, bis sich das Layout stabilisiert hat, und schreibt das Ergebnis dann als scene.json statt als HTML-Datei, womit das Problem des reinen HTML-Parsings ganz umgangen wird. Der Ablauf für eine React- oder Vue-Seite, einschließlich wie die CLI mit clientseitigem Routing umgeht, ist in eine React- oder Vue-Seite nach Figma importieren beschrieben.

Das Fazit

Von Chromes drei Speichern-unter-Optionen liefert keine ohne einen zusätzlichen Schritt eine einsatzbereite einzelne Datei so, wie ein eigenständiger HTML-Importer sie erwartet. Webseite, komplett zerfällt in zwei Teile, die zusammen bleiben müssen. Webseite, nur HTML verwirft die Ressourcen vollständig. MHTML bündelt alles, aber in einem MIME-Container, nicht in reinem HTML, und jedes JavaScript, das nach dem Laden gelaufen ist, ist so oder so verschwunden, egal welcher der drei Modi die Datei erzeugt hat. Für eine überwiegend statische Seite ist eine Capture-Erweiterung, die CSS und Bilder als Daten-URIs in eine echte .html-Datei einbettet, der zuverlässige Weg, mit den rund 33 Prozent Base64-Overhead als Preis der Portabilität. Das Safari-Web-Archive und die Live-Capture-CLI sind die richtigen Alternativen, wenn Speichern unter die Aufgabe nicht erledigen kann: das Web-Archive, wenn du ohnehin auf einem Mac bist, die CLI, wenn die Seite ihren Inhalt erst nach dem initialen Laden mit JavaScript rendert. Sobald ein Import als Layer landet, siehe einen Import in wiederverwendbare Komponenten verwandeln für den nächsten Schritt. Und falls eine Aufnahme größer ausfällt, als die kostenlose Stufe erlaubt, entfernt die Pro-Stufe auf der Preisseite die Begrenzung von 500 Ebenen.