Screenshots von DOM-Elementen erfassen: Server Side VS. Client-seitige Ansätze

Vor ein paar Wochen schrieb ich über Chatilyzer - ein neues Nebenprojekt, an dem ich im letzten Monat gearbeitet habe.

Schneller Überblick über die App und den App-Fluss: Mit Chatilyzer können Sie Statistiken über Ihre WhatsApp-Chats abrufen. Damit die App funktioniert, müssen Sie eine exportierte * .txt-Datei eines WhatsApp-Chats hochladen. Chatilyzer analysiert und analysiert den Text und extrahiert einige interessante Daten daraus. Anschließend werden Sie zu einer Ergebnisseite weitergeleitet, auf der Sie eine schöne Visualisierung der Aktivität Ihres Chats sehen.

Ein Beispiel für eine Chatilyzer-Ergebnisseite

Eine der Herausforderungen, die ich bei der Entwicklung dieser Web-App hatte, bestand darin, den Benutzern zu ermöglichen, einen Screenshot der Ergebnisseite zu erstellen und herunterzuladen, damit sie ihn in ihrer Gruppe freigeben können, anstatt eine URL für die Seite freizugeben.

Serverseitiger Ansatz (NodeJS)

Ich habe mit dem serverseitigen Ansatz begonnen, bei dem PhantomJS und ein NPM-Modul namens „Node Webshot“ verwendet wurden. Es hat eine sehr einfache API, mit der Sie Screenshots von einer bestimmten URL erstellen können:

Webshot aus 'Webshot' importieren;

Webshot ('https://chatilyzer.com', 'chat.png', Funktion (err) {
  // Screenshot jetzt in chat.png gespeichert
});

Nachdem ich den Screenshot erstellt hatte, musste ich ihn in einen Cloud-Speicher hochladen und die URL des Bildes an den Client zurücksenden, damit der Benutzer das Bild herunterladen konnte.

Vorteile:

  • Ein gebrauchsfertiges Modul.
  • Der Screenshot wird in der Cloud gespeichert, sodass er jederzeit verfügbar ist.
  • Flexible API, mit der Sie die gewünschte Breite und Höhe des Screenshots einstellen können.

Nachteile:

  • Alles oder nichts - Der Screenshot erfasst alle Seiten und Sie können ein bestimmtes Element, das Sie erfassen möchten, nicht steuern.
  • Rendern - Wenn Sie warten müssen, bis das asynchrone JS geladen ist, bevor Sie den Screenshot erfassen, können Probleme auftreten.
  • Umgebung - Da Sie sich nicht in einer echten Browserumgebung befinden, behandelt PhantomJS benutzerdefinierte / Google-Schriftarten nicht ordnungsgemäß. Dies führt dazu, dass in Ihrem Screenshot eine Standardschrift gerendert wird.
  • Speicher - Nachdem Sie den Screenshot erstellt haben, müssen Sie ihn in einem Cloud-Speicher speichern, um dem Benutzer eine gültige Bild-URL zurückzugeben. Sie benötigen also einen Cloud-Speicheranbieter, der möglicherweise mehr Geld kostet.
  • Sicherheit - Wenn die Daten des Screenshots vertraulich sind, ist das Speichern einer Kopie in der Cloud kein guter Ansatz.

BEARBEITEN: Nachdem die Community ein Feedback erhalten hat, stellt sich heraus, dass es eine andere serverseitige Lösung gibt, die ein NPM-Modul namens "Puppeteer" verwendet, das auf headless Chrome ausgeführt wird. So erstellen Sie einen Screenshot mit Puppeteer:

const puppeteer = erfordern ('puppeteer');

(async () => {
  const browser = warte auf puppeteer.launch ();
  const page = warte auf browser.newPage ();
  warte page.goto ('https://chatilyzer.com');
  warte auf page.screenshot ({path: 'chatilyzer.png'});

  warte auf browser.close ();
}) ();

Dieses Modul behebt die Probleme mit "Alles oder nichts", dem Rendern und der Umgebung, da es dieselbe Render-Engine wie Chrome bietet.

Client-seitiger Ansatz

Ich fand das Ergebnis des serverseitigen Ansatzes nicht gut genug für meinen Anwendungsfall und begann, andere Optionen zu untersuchen.

Ich habe eine extrem coole JS-Bibliothek namens "html2canvas" gefunden, die, wie der Name schon sagt, ein HTML-Element in ein Canvas-Element verwandelt.

html2canvas website

Wie Sie sehen, ist es auch sehr einfach zu bedienen. Grundsätzlich rufen Sie die html2canvas-Methode auf und übergeben ein DOM-Element als Argument. Diese Methode gibt eine Zusage zurück, die Sie zum Extrahieren eines Canvas-Elements verwenden können.

html2canvas (document.querySelector ("# capture"). then (canvasElm => {
    document.body.appendChild (canvasElm);
});

Als Nächstes möchten Sie Ihrem Benutzer das Herunterladen des Screenshots ermöglichen.

Verwenden Sie dazu die Methode JS toDataURL (siehe unten):

// Eine Base64-Datenzeichenfolge abrufen
var imageType = 'image / png';
var imageData = canvasElm.toDataURL (imageType);
// Öffnen Sie den Datenstring im aktuellen Fenster
document.location.href = imageData.replace (imageType, 'image / octet-stream');

Es gibt eine weitere JS-Bibliothek namens "canvas2image". Ich empfehle, es zu verwenden, anstatt es selbst zu schreiben, da es mehr Flexibilität bietet und es Ihnen auch ermöglicht, ein Bild-Tag aus dem Canvas-Element zu generieren. Sie können also das gleiche Ergebnis erzielen, indem Sie Folgendes verwenden:

Canvas2Image.saveAsPNG (canvasElm, width, height);

Vorteile:

  • WYSIWYG - Das Ergebnis ist 1: 1 von dem, was Sie auf dem Bildschirm sehen.
  • Keine Serverseite - Alle im Browser ausgeführt.
  • Sicherheit - Wenn die Daten des Screenshots vertraulich sind, können Sie sie auf Client-Seite viel sicherer erfassen, da der Server die Ergebnisse nicht kennt und keine Kopie an anderer Stelle speichert.

Nachteile:

  • Kompatibilität - html2canvas wird nicht in allen Browsern unterstützt
  • Teuer - Obwohl html2canvas ein Versprechen zurückgibt, ist es immer noch eine teure Aktion. Bei großen und komplizierten Komponenten kann es einige Sekunden dauern, bis Ergebnisse erzielt werden.
  • Schmale Ansicht - Wenn Sie einen schmalen Bildschirm verwenden (z. B. für Mobilgeräte), wird der Screenshot schmal und der Screenshot aus der tatsächlichen Ansicht erfasst (dies kann gelöst werden, indem entweder eine feste Breite als Argument an canvas2html übergeben wird oder indem Sie im Hintergrund einen iFrame mit der gewünschten Breite öffnen, dort den Screenshot aufnehmen und die Bilddaten mit postMessage zurücksenden).
  • Elementunterstützung - In html2canvas werden nicht alle HTML-Elemente unterstützt. Beispielsweise werden andere Canvas-Elemente, Iframes und Flash überhaupt nicht gerendert.

Abschließend

Es gibt zwei Ansätze zum Erfassen eines Screenshots aus HTML-Elementen. Überlegen Sie sich, was für Ihre App erforderlich ist.

Der serverseitige Ansatz ist derjenige, den Sie wählen, wenn Sie eine browser- / plattformübergreifende Erfahrung benötigen und nicht sicher sind, ob Ihre Benutzer über den richtigen Browser verfügen, um den Screenshot aufzunehmen. Der Preis, den Sie zahlen müssen, bezieht sich sowohl auf die physische Zahlung für den Cloud-Speicherdienst als auch auf die ungenauen Ergebnisse.

Der clientseitige Ansatz ist gut, wenn Sie sicher sind, dass Ihre Benutzer über einen Browser verfügen, der den Screenshot erfassen kann (oder wenn Sie bereit sind, den Preis für diejenigen zu zahlen, die dies nicht tun), und wenn Genauigkeit für den Screenshot ein Muss ist.

Schneller Gedanke - Ich denke, der beste Ansatz ist es, zwischen ihnen zu kombinieren. Sie können überprüfen, ob die Browserkompatibilität des Benutzers die Unterstützung bietet, die Sie zum Aufnehmen eines Screenshots benötigen. Andernfalls können Sie auf den serverseitigen Ansatz zurückgreifen.

Ich hoffe, Ihnen hat der Artikel gefallen. Klatsch, es hat dir gefallen :)

Kennen Sie andere Möglichkeiten, um mit NodeJS Screenshots von Webseiten zu erstellen? In Kommentaren teilen!