Bun.Image macht Ihre gesamte Bild-Pipeline überflüssig

BBetter Stack
Computing/SoftwareInternet Technology

Transcript

00:00:00Das ist Bun Image, eine in Bun 1.3.14 integrierte Bildverarbeitungs-API, die das Grösse ändern,
00:00:06Zuschneiden und Konvertieren von Bildern zwischen verschiedenen Formaten ohne native Abhängigkeiten ermöglicht,
00:00:10und das Ganze läuft ausserhalb des Hauptthreads, was bedeutet, dass dein Server während der Verarbeitung
00:00:14nicht blockiert wird. Aber Bun ist doch bereits eine Laufzeitumgebung, ein Paketmanager, ein Bundler, ein Test-Runner
00:00:19und jetzt auch noch ein Bildverarbeiter? Ist das alles viel zu viel oder verrät es uns etwas
00:00:24Grösseres darüber, wohin sich Bun entwickelt? Abonniere den Kanal und lass es uns herausfinden.
00:00:30Wenn du schon mal Bilder auf dem Server mit JavaScript verarbeitet hast, hast du vielleicht eine Bibliothek namens
00:00:35Sharp verwendet, ohne es überhaupt zu wissen. Sie hat wöchentlich über 55 Millionen Downloads auf npm und wird sogar
00:00:41von Next.js im Hintergrund zur Bildoptimierung eingesetzt. Aber Sharp basiert auf einer nativen Binärdatei namens libvips,
00:00:47weshalb bei jeder Installation das passende Build für deine Plattform geladen werden muss. Und wenn du schon mal
00:00:51einen Docker-Build- oder CI-Pipeline-Fehler deswegen hattest, weisst du, wie frustrierend das ist. Deshalb hat sich Bun entschlossen,
00:00:57die Bildverarbeitung direkt in die Laufzeitumgebung einzubauen, und sie ist in den meisten
00:01:02Benchmarks tatsächlich schneller als Sharp. Das Lesen von Metadaten ist bis zu 70-mal schneller und das Skalieren etwa 30 % schneller. Nun sind viele
00:01:08Entwickler wirklich verwirrt, warum Bun das hinzugefügt hat, aber ich verstehe ungefähr, wohin das führt,
00:01:13und ich werde dir später mehr dazu erzählen. Schauen wir uns aber erst einmal ein paar Demos an, wie man
00:01:17die Bun-Image-API verwendet. Wir probieren das an meinem Blog aus, einer statischen Waku-Website,
00:01:22die ein paar riesige Bilder enthält. Zu Beginn schauen wir uns ein einfaches Skript an, das ein einzelnes Bild optimiert,
00:01:27nämlich das Profilbild mit meinem Gesicht, und die Dateigrösse lässt sich damit um unglaubliche 99 % reduzieren.
00:01:33Schauen wir uns an, wie das geht. Zuerst rufen wir das Bild ab – beachte, dass wir hier Bun.image verwenden, du könntest aber auch
00:01:37Bun.file mit der Image-Funktion nutzen. Dann skalieren wir das Bild, um seine Grösse zu verringern, indem wir eine Breite von 800 Pixeln vorgeben,
00:01:43wobei die Höhe automatisch basierend auf dem Seitenverhältnis berechnet wird. Wenn du möchtest,
00:01:47könnten wir diese hier ebenfalls angeben. Danach legen wir als Ausgabeformat WebP mit reduzierter Qualität fest. Natürlich
00:01:52werden auch andere Ausgabeformen unterstützt, und dann speichern wir das neue Bild als Datei,
00:01:56was ein Promise ist, weshalb das await-Schlüsselwort erforderlich ist. Und Sie sehen, wie einfach das ist.
00:02:01Tatsächlich ist all dieser Code hier überflüssig, wir können ihn also entfernen und den Code noch einfacher gestalten.
00:02:06Wir können auch einen Skalierungsfilter festlegen, den Resampling-Kernel ändern und die Bildgrösse weiter reduzieren.
00:02:10Wir können das Bild drehen oder spiegeln, was wirklich cool ist. Wir können sogar die Helligkeit oder
00:02:15Sättigung anpassen, was allerdings zu ziemlich merkwürdig aussehenden Bildern führen kann. Es gibt jedoch etwas sehr Cleveres,
00:02:19das du bei langsamen Verbindungen tun kannst: die Placeholder-Funktion nutzen, um automatisch
00:02:23ein verschwommenes Bild anzuzeigen, während das Hauptbild noch lädt. Dazu verwende ich diese Schleife,
00:02:29die jede einzelne Datei mit diesen Endungen in dem Verzeichnis durchläuft, das alle
00:02:34Blog-Bilder enthält. Jedes Bild wird also in der Grösse angepasst, verkleinert ohne zugeschnitten zu werden, und nicht
00:02:39hochskaliert. Dann erstellen wir für jedes Bild einen Platzhalter, der einen ThumbHash erzeugt, also
00:02:45jedes Bild in einen 28-Byte-Hash codiert – perfekt als Platzhalter für ein verschwommenes Bild.
00:02:49Dieser Hash wird einem Platzhalter-Objekt hinzugefügt und dann in eine Datei geschrieben,
00:02:53die so aussieht. Der Grund, warum der Platzhalter ein Base64-Bild und kein
00:02:58separates kleineres WebP-Bild ist, besteht darin, dass das Netzwerk keine zusätzliche Anfrage zum Abrufen stellen muss.
00:03:02Ich kann also alle Platzhalter importieren und sie als Hintergrundbild in CSS einfügen,
00:03:07während ich darauf warte, dass das Hauptbild geladen wird, was für jedes Bild auf meinem Blog funktioniert.
00:03:11Wenn du das für ein einzelnes Bild in einer MDX-Datei tun möchtest, kannst du den Base64-Code einfach
00:03:16manuell hinzufügen, was genauso gut funktioniert. Übrigens lässt sich ein ähnliches Verhalten
00:03:20auch mit JPEG-Bildern erzielen, indem man progressive auf true setzt. Natürlich gibt es noch viele weitere Dinge, die Bun Image
00:03:24unterstützt, auf die ich noch nicht eingegangen bin, wie das Abrufen von Bildern aus einem S3-kompatiblen
00:03:28Bucket, das Speichern von Bildern in einem Bucket, die Verwendung der Image-Pipeline als gültiger Response-Body
00:03:33sowie die Konfiguration eines Fallback-Formats, falls ein bestimmtes Betriebssystem eines nicht unterstützt.
00:03:37Lohnt sich das Ganze also? Nun, wenn du bereits Bun nutzt, dann auf jeden Fall, das ist ein Kinderspiel.
00:03:41Wenn du jedoch Node verwendest, funktioniert Sharp hervorragend und ist kampferprobt,
00:03:45und es besteht kein Grund, nur für die Bildverarbeitung zu einer völlig anderen Laufzeitumgebung zu wechseln.
00:03:49Erinnerst du dich, als ich sagte, es gäbe einen wichtigeren Grund für diesen Schritt von Bun? Wenn man sich ansieht, was Bun
00:03:54im letzten Jahr alles gemacht hat – integriertes SQLite, S3, Postgres und jetzt Bilder –, ist das im Grunde
00:03:59alles, was man für eine Full-Stack-App braucht, abgesehen von vielleicht Authentifizierung und E-Mail. Das lässt mich fragen:
00:04:04Versucht Bun, das Laravel oder Rails für JavaScript zu bauen, aber direkt auf Runtime-Ebene? Wenn dem so ist,
00:04:11wird als Nächstes die Authentifizierung dran sein. Und wenn das passiert, erinner dich daran: Du hast es hier zuerst gehört.
00:04:15Leider kann man heutzutage über Bun sprechen, ohne den riesigen Rewrite von Zig zu Rust zu erwähnen,
00:04:20der – hoffentlich – in der nächsten Version erscheinen wird. Hoffen wir, dass alles glattgeht.
00:04:25Apropos Zig: Wenn du mehr über Vercels Language Zero erfahren möchtest, das wie Zig aussieht,
00:04:29aber kein Zig ist und für KI-Agenten entwickelt wurde, schau dir dieses Video von James an.

Key Takeaway

Bun.Image integriert eine native Bildverarbeitungs-API in die JavaScript-Laufzeitumgebung Bun, die gängige Bibliotheken wie Sharp in Benchmarks bei der Skalierung und Metadaten-Verarbeitung deutlich übertrifft.

Highlights

  • Bun 1.3.14 integriert die Bildverarbeitungs-API Bun.Image für die direkte Bearbeitung ohne native Abhängigkeiten.

  • Das Lesen von Bildmetadaten läuft mit Bun.Image bis zu 70-mal schneller als mit herkömmlichen Bibliotheken wie Sharp.

  • Die Skalierung von Bildern erfolgt mit Bun.Image etwa 30 Prozent schneller im Vergleich zu Sharp auf Basis von libvips.

  • Bun.Image läuft ausserhalb des Hauptthreads, wodurch der Server während rechenintensiver Bildoperationen nicht blockiert wird.

  • ThumbHash kodiert Bilder in einen 28-Byte-Hash zur Generierung nahtloser Platzhalter ohne zusätzliche Netzwerkanfragen.

Timeline

Einführung in Bun.Image und Probleme mit herkömmlichen Bibliotheken

  • Bun 1.3.14 enthält Bun.Image zur serverinternen Bildverarbeitung ohne native Abhängigkeiten.
  • Die bisher dominierende Bibliothek Sharp basiert auf der nativen Binärdatei libvips und erzeugt häufig Build-Fehler.
  • Bun.Image verarbeitet Metadaten bis zu 70-mal schneller und skaliert Bilder etwa 30 Prozent schneller als Sharp.

Die integrierte Bildverarbeitungs-API ermöglicht Grösse ändern, Zuschneiden und Konvertieren ausserhalb des Hauptthreads. Dadurch bleibt der Server während der Ausführung reaktionsfähig. Die bisher übliche Nutzung von Sharp erfordert plattformabhängige Binärdateien, was zu Komplikationen in Docker-Containern und CI-Pipelines führt. Die Laufzeitumgebung löst diese Hürden durch eine direkte Integration in den Kern.

Praktische Anwendung und Bildoptimierung am Beispiel

  • Die Skalierung eines Profilbildes mit einer Zielbreite von 800 Pixeln reduziert die Dateigrösse drastisch.
  • Ausgabeformate wie WebP lassen sich mit angepasster Qualität und frei wählbarem Resampling-Kernel definieren.
  • ThumbHash kodiert Bilder in einen 28-Byte-Hash als Base64-String für sofort verfügbare CSS-Hintergrund-Platzhalter.

Anhand einer statischen Waku-Website zeigt die Anwendung die direkte Skalierung, Formatkonvertierung und Speicherung als Promise-basierte Operation. Neben der Grössenanpassung lassen sich Filter anwenden sowie Helligkeit und Sättigung steuern. Für langsame Verbindungen generiert ein Schleifenskript ThumbHash-basierte Platzhalter als Base64-Code. Dieser Inline-Ansatz verhindert zusätzliche Netzwerkanfragen beim Laden der Website.

Erweiterte Funktionen und strategische Einordnung von Bun

  • Bun Image unterstützt S3-kompatible Buckets, Response-Bodies und flexible Fallback-Formate.
  • Die Integration von SQLite, S3, Postgres und Bildverarbeitung deckt wesentliche Bausteine von Full-Stack-Anwendungen ab.
  • Die kontinuierliche Erweiterung um plattformnahe Dienste positioniert Bun als integriertes Backend-Framework direkt auf Runtime-Ebene.

Zusätzlich zur lokalen Dateiverarbeitung verarbeitet Bun.Image Ressourcen direkt aus S3-Buckets und gibt sie als gültige HTTP-Antworten aus. Die schrittweise Ergänzung von Datenbanken, Objektspeichern und Medien-Pipelines verdeutlicht eine strategische Entwicklung hin zu einer umfassenden Plattform für Webanwendungen. Sollte die Authentifizierung als Nächstes folgen, übernimmt Bun ähnliche Rollen wie Laravel oder Rails direkt in der JavaScript-Infrastruktur.

Community Posts

View all posts