1 Punkte von GN⁺ 2025-01-25 | 1 Kommentare | Auf WhatsApp teilen
  • Bun 1.2 ist ein großes Release mit dem Ziel, ein Full-Stack-Entwicklungstool für JavaScript/TypeScript zu sein, und erweitert Node.js-Kompatibilität sowie Runtime, Bundler, Tests und Paketmanager gemeinsam
  • Die Kompatibilitätsprüfung wurde verstärkt, indem bei jeder Änderung die Node.js-Testsuite ausgeführt wird; Unterstützung für node:http2, node:dgram, node:cluster, node:zlib und node:v8 wurde hinzugefügt
  • Die neuen integrierten APIs Bun.s3 und Bun.sql bringen den Zugriff auf S3-kompatiblen Objektspeicher und Postgres direkt in die Runtime und reduzieren damit Abhängigkeiten von externen Clients
  • Der Paketmanager stellt das Standard-Lockfile vom binären bun.lockb auf das JSONC-basierte bun.lock um und ergänzt .npmrc, bun publish, bun patch, bun outdated sowie bun run --filter
  • Das Arbeitsverzeichnis von bun run, die Fehlerbehandlung von Bun.build(), der Rückgabewert von server.stop(), bun -p und die Standardwerte für Sourcemaps haben sich geändert; bestehende Projekte sollten daher die Auswirkungen auf Migrationen prüfen

Stärkere Node.js-Kompatibilität

  • Bun 1.2 ändert den Prozess zur Verbesserung der Kompatibilität so, dass bei jeder Bun-Änderung die Node.js-Testsuite ausgeführt wird
    • Bisher wurden Fehler vor allem anhand von GitHub-Issues oder Berichten über fehlgeschlagene npm-Pakete behoben; dieser Ansatz ähnelte eher einem „Whac-a-Mole“-Spiel und erschwerte größere Refactorings
    • Tausende Testdateien aus dem Node.js-Repository wurden auf Bun portiert, und diese Tests werden bei jedem Commit ausgeführt, um die Kompatibilität zu prüfen
  • Da Node.js-Tests teils interne Implementierungsdetails und exakte Fehlermeldungen prüfen, ersetzt Bun in einigen Tests interne Bindings durch eigene Stubs oder passt die Prüfung stärker auf name und code an
    • Bun versucht, die Fehlermeldungen von Node.js so weit wie möglich anzugleichen, bietet aber in manchen Fällen hilfreichere Meldungen, wenn name und code identisch sind
  • Neu unterstützte Node.js-Module und -Funktionen
    • node:http2: Unterstützung zum Erstellen von HTTP/2-Servern, auch für gRPC-Server erforderlich
    • node:dgram: Unterstützung für bind/connect bei UDP-Sockets
    • node:cluster: Mehrere Bun-Instanzen können ausgeführt werden, um Arbeit auf mehrere CPU-Kerne zu verteilen
    • node:zlib: Die JavaScript-Implementierung wurde in nativen Code neu geschrieben und ist 2-mal schneller als in Bun 1.1
    • node:v8: Mit getHeapSnapshot und writeHeapSnapshot lässt sich der Bun-Heap in Chrome DevTools untersuchen
  • Der node:http2-Server ist in Bun 1.2 2-mal schneller als in Node.js
  • express verarbeitet HTTP-Requests dank verbesserter node:http-Kompatibilität und Optimierungen am Bun-HTTP-Server bis zu 3-mal schneller als Node.js
  • Unterstützung für C++-Add-ons, die die V8-C++-API verwenden, wurde ebenfalls hinzugefügt
    • Da Node.js V8 verwendet, Bun aber JavaScriptCore, ist die Implementierung sehr anspruchsvoll
    • Bun implementiert die öffentliche C++-API von V8 auf JavaScriptCore, sodass Pakete wie cpu-features funktionieren
    • Die Unterstützung der V8-C++-API ist komplex, daher können bei den meisten Paketen noch Funktionen fehlen; die Unterstützung für Pakete wie node-canvas@v2 und node-sqlite3 wird weiter verbessert

Integrierte S3-API Bun.s3

  • Bun 1.2 ergänzt mit Bun.s3 eine integrierte API für S3-kompatiblen Objektspeicher
    • Sie kann mit Diensten verwendet werden, die die S3-API implementieren, etwa Amazon S3, Google Cloud Storage und Cloudflare R2
    • Lesen, Schreiben und Löschen von Dateien erfolgt über eine API, die mit dem Webstandard Blob kompatibel ist
  • s3.file() gibt eine verzögerte Referenz auf eine S3-Datei zurück und kann wie die Bun-File-API mit text(), json(), arrayBuffer() und stream() verwendet werden
  • Buns S3-Client ist nicht in JavaScript, sondern in nativem Code geschrieben
    • Im Vergleich zur Nutzung von @aws-sdk/client-s3 unter Node.js ist das Herunterladen von Dateien aus S3-Buckets 5-mal schneller
  • Für Schreibvorgänge stehen write() und writer() bereit
    • write() kann Strings, Uint8Array, Blob, Response und mehr hochladen
    • writer() führt Multipart-Uploads für große Dateien aus
  • presign() erzeugt eine Presigned URL, die den Upload einer bestimmten Datei erlaubt
    • Nutzer können direkt nach S3 hochladen, ohne ihnen Zugangsdaten offenzulegen oder dem Bucket unnötige Zugriffsrechte zu geben
  • Bei Verwendung mit Bun.serve() leitet new Response(s3.file(...)) auf eine Presigned URL weiter, statt dass der Server die S3-Datei herunterlädt und erneut ausliefert
    • Das reduziert Speicherbedarf, Zeitaufwand und Bandbreitenkosten für den Dateidownload durch den Server
  • s3://-URLs können auch mit Bun.file() und fetch() verwendet werden
    • Mit fetch("s3://...") sind Upload, Download und Löschen möglich
    • Der standardmäßige S3Client wird über Umgebungsvariablen wie AWS_ACCESS_KEY_ID und AWS_SECRET_ACCESS_KEY konfiguriert

Integrierter Postgres-Client Bun.sql

  • Bun 1.2 ergänzt mit Bun.sql einen integrierten SQL-Client mit Postgres-Unterstützung
    • Bun bot bereits einen integrierten SQLite-Client; mit diesem Release wird die Unterstützung für SQL-Datenbanken erweitert
    • Es gibt auch einen Pull Request, der MySQL-Unterstützung hinzufügt
  • Bun.sql führt SQL über Tagged-Template-Literals aus
    • JavaScript-Werte können als SQL-Parameter übergeben werden
    • String-Escaping und Prepared Statements werden automatisch verwendet, um SQL Injection zu verhindern
  • Ergebnisse werden als Array von Objekten zurückgegeben, deren Schlüssel die Spaltennamen sind
  • Die Implementierung nutzt nativen Code und mehrere Optimierungen
    • automatische Prepared Statements
    • Query Pipelining
    • binäres Wire Protocol
    • Connection Pooling
    • Struktur-Caching
  • Beim Lesen von Zeilen ist es bis zu 50 % schneller als die Nutzung beliebter Postgres-Clients unter Node.js
  • Die API ist von postgres.js inspiriert und so gestaltet, dass der Wechsel von bestehendem Code zum integrierten SQL-Client von Bun einfach ist

Änderungen am Paketmanager

  • Bun 1.2 ändert das standardmäßige Lockfile vom binären bun.lockb auf das textbasierte bun.lock
    • bun.lockb half dabei, bun install fast 30-mal schneller als npm zu machen, aber die Inhalte waren auf GitHub schwer einsehbar und Pull-Request-Reviews sowie das Auflösen von Merge-Konflikten waren schwierig
    • Auch Tools wie Dependabot hatten Schwierigkeiten, das Lockfile zu lesen
  • bun.lock ist eine JSONC-Datei
    • Unterstützt Kommentare und trailing commas
    • Pull-Request-Diffs lassen sich leichter prüfen, und trailing commas verringern die Wahrscheinlichkeit von Merge-Konflikten
  • Neue Projekte erzeugen bun.lock
    • Bestehende Projekte mit bun.lockb werden ohne automatische Migration weiterhin mit dem binären Lockfile unterstützt
    • bun.lockb wird langfristig unterstützt und auch von bun add und bun update weiterhin aktualisiert
    • Eine Migration auf das neue Text-Lockfile ist mit bun install --save-text-lockfile möglich
  • bun install ist auch nach dem Wechsel auf das Text-Lockfile 30 % schneller als in Bun 1.1
  • In package.json können Kommentare und trailing commas verwendet werden
    • Auch require() und import() können eine solche package.json lesen
    • Da dies im gesamten JavaScript-Ökosystem keine breit unterstützte Funktion ist, wird empfohlen, sie „at your own risk“ zu verwenden
  • Unterstützung für .npmrc wurde hinzugefügt
    • Liest .npmrc im Projekt-Root und im Home-Verzeichnis
    • Kann für Registry-, scoped-package- und Authentifizierungseinstellungen für private Registries verwendet werden
  • Neue Paketmanager-Befehle und -Optionen
    • bun run --filter: dasselbe Skript gleichzeitig in mehreren Workspaces ausführen
    • bun outdated: veraltete Abhängigkeiten prüfen
    • bun publish: Ersatz für npm publish, unterstützt .npmrc-Authentifizierung, Tarball-Packing, OTP und Edge Cases in package.json
    • bun patch: Änderungen an Abhängigkeiten als .patch-Dateien in patches/ speichern und bei bun install automatisch anwenden
    • --omit=dev|optional|peer: dev-, optional- und peer-Abhängigkeiten bei der Installation ausschließen
    • CA-Zertifikate können in bunfig.toml, per CLI-Flag und in .npmrc konfiguriert werden
    • Ebenfalls unterstützt werden bundleDependencies sowie das Beibehalten der Einrückung in package.json bei bun add

Verbesserungen am Test-Runner

  • bun test unterstützt einen JUnit-XML-Reporter
    • Mit bun test --reporter=junit --reporter-outfile=junit.xml können Testergebnisse an CI/CD-Tools wie Jenkins, CircleCI und GitLab CI übergeben werden
    • JUnit-Reporting kann auch in bunfig.toml konfiguriert werden
  • Für Code Coverage wurde ein LCOV-Reporter hinzugefügt
    • bun test --coverage --coverage-reporter=lcov erzeugt coverage/lcov.info
    • Mit --coverage-dir lässt sich das Ausgabeverzeichnis ändern
  • Inline Snapshots werden mit expect().toMatchInlineSnapshot() unterstützt
    • Mit bun test -u oder --update-snapshots werden Snapshots in der Testdatei aktualisiert
    • Auch toThrowErrorMatchingSnapshot() und toThrowErrorMatchingInlineSnapshot() können verwendet werden
  • test.only() funktioniert nicht mehr nur mit dem Flag --only, sondern auch ohne dieses
  • Der expect()-API wurden Matcher wie in Jest, Vitest und jest-extended hinzugefügt
    • toContainValue(), toContainKey() und die toHaveReturned()-Familie
    • Als zweites Argument kann eine benutzerdefinierte Fehlermeldung übergeben werden
  • Mit jest.setTimeout() und setDefaultTimeout() lässt sich das Standard-Test-Timeout für den aktuellen Scope oder das aktuelle Modul ändern

Bundler- und Build-Funktionen

  • Bun 1.2 unterstützt HTML import
    • Wird eine HTML-Datei an die Option static von Bun.serve übergeben, werden <script> und <link> in der HTML-Datei automatisch gebundelt und als statische Route bereitgestellt
  • bun build --compile unterstützt Cross-Compilation
    • Unter Linux lassen sich Windows- oder macOS-Binaries erstellen, und auch die umgekehrte Richtung ist möglich
    • Bei Windows-Builds können ein Icon gesetzt und das Konsolenfenster ausgeblendet werden
  • bun build --bytecode erzeugt einen Bytecode-Cache
    • Damit kann die Startzeit von Anwendungen wie eslint um den Faktor 2 beschleunigt werden
    • .jsc-Dateien enthalten den Bytecode-Cache der jeweiligen .js-Datei; beide Dateien werden zur Ausführung benötigt
    • Der Bytecode-Cache kann achtmal so groß sein wie der Quellcode und verbraucht zugunsten schnellerer Startzeiten mehr Speicherplatz
  • Mit bun build --format=cjs kann CommonJS als Ausgabeformat angegeben werden
    • Zuvor wurde nur ESM unterstützt
    • Das erleichtert die Erstellung von Bibliotheken oder Anwendungen für ältere Node.js-Versionen
  • Die CommonJS-Erkennung wurde verbessert
    • Wenn eine Datei mehrdeutig ist, wird die "use strict"-Direktive am Anfang als letzte Heuristik für CommonJS verwendet
    • require.main === module wird zu import.meta.main umgeschrieben und kann zusammen mit import-Anweisungen verwendet werden
  • Der Plugin-API wurde der Hook onBeforeParse() hinzugefügt
    • Er muss nicht in JavaScript, sondern als N-API-Addon implementiert werden
    • In kompilierten Sprachen wie Rust, C/C++ oder Zig kann damit Quellcode unmittelbar vor dem Parsen mit nahezu keinem Overhead bearbeitet werden
    • Es handelt sich um eine fortgeschrittene API für Plugin- und Framework-Autoren
  • Auch die Build-Optionen wurden erweitert
    • Umgebungsvariablen mit --env="PUBLIC_*" in das Bundle injizieren
    • Funktionsaufrufe etwa mit --drop=console entfernen
    • Banner/Footer hinzufügen
    • Mit Bun.embeddedFiles() die Liste der in einem standalone executable enthaltenen Dateien anzeigen
    • Mit --ignore-dce-annotations fehlerhafte Dead-Code-Elimination-Annotationen ignorieren
    • Mit --packages=external festlegen, dass Paketabhängigkeiten nicht ins Bundle aufgenommen werden

CSS-Bundling

  • Bun 1.2 implementiert einen neuen CSS-Parser und -Bundler
    • Er basiert auf Arbeiten von LightningCSS und wurde von Rust nach Zig neu geschrieben, um in Buns JavaScript/TypeScript-Parser, Bundler und Runtime integriert zu werden
  • Mit bun build ./index.css können mehrere CSS-Dateien sowie @import-, url- und @font-face-Referenzen zu einer einzigen CSS-Datei zusammengeführt werden
  • .css-Dateien können aus JavaScript- und TypeScript-Code importiert werden
    • Aus dem JavaScript-Module-Graph importiertes CSS und @import-Regeln werden pro Entrypoint zu einer einzelnen CSS-Datei abgeflacht
  • Auch über die API Bun.build() lassen sich CSS und JavaScript mit derselben API bundeln

Ergänzungen der Bun-Runtime-API

  • Bun.serve() unterstützt über die Eigenschaft static statische Routen
    • Der Pfad wird als Schlüssel und ein Response-Objekt als Wert übergeben
    • Statische Routen sind bis zu 40 % schneller als die direkte Verarbeitung im fetch()-Handler
    • Response Body, Header und Statuscode werden im Speicher gecacht, sodass keine JavaScript-Allocation und keine Garbage Collection anfällt
    • Mit server.reload() lassen sich statische Routen neu laden
  • Bun.udpSocket() stellt einen UDP-Socket in Form einer Bun-API bereit
    • Auch node:dgram wird unterstützt, aber Bun.udpSocket() ist eine moderne API ähnlich dem bestehenden Bun.listen()
    • Mehrere UDP-Datagramme können mit einem einzigen Syscall gesendet werden, und OS-Backpressure wird berücksichtigt
  • Bun.file() unterstützt delete(), unlink() und stat()
    • stat() gibt Metadaten in derselben Form wie das Stats-Objekt von Node.js fs.stat() zurück
    • Dieselbe API kann auch für S3-Dateien verwendet werden
  • Bun.color() bietet Farb-Parsing, Normalisierung und Konvertierung
    • Unterstützt CSS, ANSI-Farbcodes, RGB, HSL usw.
  • dns.prefetch() kann DNS-Records vorab abrufen und den DNS-Cache beim Start aufwärmen
  • Weitere Utilities
    • Bun.inspect.table(): gibt wie console.table einen String im Tabellenformat zurück
    • Bun.randomUUIDv7(): erzeugt monotone UUID v7, geeignet für Sortierung und Datenbanken

Verbesserungen am SQLite-Client

  • Der in Bun integrierte SQLite-Client kann mit query.as(Class) Query-Ergebnisse auf Klasseninstanzen mappen
    • Getter, Setter und Methoden können hinzugefügt werden
    • Aus Performancegründen werden Klassenkonstruktoren, Default Initializer und private Felder nicht unterstützt
    • Da keine Beziehungen verwaltet und kein SQL generiert wird, ist es kein ORM
  • query.iterate() verarbeitet Zeilen per Iterator, ohne sie alle auf einmal in den Speicher zu laden
    • Auch das Query-Objekt selbst kann mit einer for-Schleife durchlaufen werden
  • Wenn die Option strict aktiviert ist, können bei Query-Parametern die Präfixe $, @ und : weggelassen werden
    • Fehlt ein Parameter, wird ein Fehler geworfen
  • Im Ergebnis von db.run() lassen sich die Anzahl der geänderten Zeilen und die letzte eingefügte Row-ID prüfen
    • changes
    • lastInsertRowid
  • Die Option safeIntegers gibt 64-Bit-Integer als BigInt zurück statt als abgeschnittene number
    • Sie kann pro Datenbank oder pro Query gesetzt werden
  • Mit der JavaScript-Syntax using können Statements und Datenbanken beim Verlassen des Scopes automatisch geschlossen werden

C aus JavaScript kompilieren und ausführen

  • Bun 1.2 fügt experimentelle Unterstützung hinzu, um C aus JavaScript heraus zu kompilieren und auszuführen
    • Verwendet die cc()-API aus bun:ffi
    • Damit lassen sich C-Systembibliotheken aus JavaScript nutzen, ohne separaten Build-Step
  • Bun enthält tinycc
    • Im Gegensatz zu gcc oder clang kann es einfachen C-Code in Millisekunden kompilieren
    • C-Code kann bei Bedarf kompiliert und ausgeführt werden
  • Auch C-Code, der N-API verwendet, wird bereitgestellt
    • Funktioniert allein mit Bun, ohne node-gyp-Build-Schritt

Unterstützung für musl und Alpine Linux

  • Bun 1.2 ergänzt Bun-Builds für Linux-Distributionen, die musl libc statt glibc verwenden
    • Nutzbar in Umgebungen wie Alpine Linux
    • Unterstützt Linux x64 und aarch64
  • In Docker kann das Image oven/bun:alpine verwendet werden
  • musl ermöglicht kleinere Container-Images, ist aber tendenziell etwas langsamer als die glibc-Version von Bun
    • Wenn es keinen speziellen Grund gibt, wird die Nutzung von glibc empfohlen

JavaScript-Sprachfeatures

  • Unterstützung für Import Attributes wurde hinzugefügt
    • JSON, Text, TOML usw. können explizit importiert werden, etwa mit import json from "./package.json" with { type: "json" }
    • Auch mit dynamischem import() nutzbar
  • using und await using werden unterstützt
    • Beim Verlassen des Scopes wird [Symbol.dispose] bzw. [Symbol.asyncDispose] aufgerufen, um Ressourcen automatisch aufzuräumen
    • Wird von mehreren Bun-APIs unterstützt, darunter Bun.spawn(), Bun.serve(), Bun.connect(), Bun.listen() und bun:sqlite
  • Neue Promise-bezogene APIs
    • Promise.withResolvers(): erzeugt promise, resolve und reject auf einmal
    • Promise.try(): umschließt eine synchrone oder asynchrone Funktion als Promise
  • Fehler- und Byte-Array-APIs
    • Error.isError(): prüft genauer, ob etwas ein Error ist, auch bei Manipulationen an der Prototype Chain oder Cross-Realm-Situationen mit node:vm
    • Uint8Array.toBase64() / Uint8Array.fromBase64()
    • Uint8Array.toHex() / Uint8Array.fromHex()
  • Iterator Helper wurden hinzugefügt
    • map, flatMap, filter, take, drop, reduce, toArray, forEach, find
  • Float16Array wird unterstützt
    • 16-Bit-Gleitkomma-Arrays haben geringere Präzision als 32-Bit-Arrays, sind aber speichereffizienter

Ergänzungen der Web APIs

  • TextDecoderStream und TextEncoderStream werden unterstützt
    • Das sind die Streaming-Versionen von TextDecoder und TextEncoder
    • In Bun ist TextEncoderStream bis zu 30-mal schneller als in Node.js
  • Die Option stream von TextDecoder wird unterstützt
    • Chunks können als Teil eines größeren Streams verarbeitet werden, auch wenn sie keinen vollständigen UTF-8-Codepoint enthalten
  • Die Methode bytes() wurde hinzugefügt
    • Gibt Stream-Daten etwa von Response, Blob oder Bun.file() als Uint8Array zurück
    • Reduziert den bisherigen Ablauf über arrayBuffer() und anschließendes Erzeugen eines Uint8Array
  • Streaming-Uploads mit fetch() werden unterstützt
    • Nützlich für Uploads großer Dateien oder Datenstreams, deren Content Length nicht vorab bekannt ist
  • console.group() und console.groupEnd() wurden implementiert
  • URL.createObjectURL() wird unterstützt
    • Erstellt aus einem Blob eine URL, die mit fetch(), Worker und import() verwendet werden kann
    • Da auch Worker-Skripte durch den Bun-Transpiler laufen, kann TypeScript-Syntax verwendet werden
  • AbortSignal.any() kombiniert mehrere AbortSignals, sodass das übergeordnete Signal ebenfalls abbricht, wenn eines davon abbricht

Verhaltensänderungen und Hinweise zur Migration

  • Das Arbeitsverzeichnis von bun run hat sich geändert
    • Bisher wurde das aktuelle Arbeitsverzeichnis der Shell verwendet
    • In Bun 1.2 wird das übergeordnete Verzeichnis von package.json als Arbeitsverzeichnis für Skripte verwendet
    • Diese Änderung dient der Angleichung an das Verhalten von npm und yarn
  • bun test meldet uncaught errors oder rejections zwischen Tests als Fehler
    • Bisher wurden solche Fehler möglicherweise nicht als Testfehler behandelt
  • server.stop() gibt jetzt Promise<void> zurück
    • Damit kann gewartet werden, bis in-flight HTTP connections geschlossen sind
  • Bun.build() rejectet bei einem Fehler, statt den Fehler in logs des aufgelösten Ergebnisses abzulegen
    • Wenn das bisherige Verhalten benötigt wird, kann throw: false gesetzt werden
  • bun -p ist nun, wie bei Node.js, ein Alias für bun --print
    • Zuvor war es ein Alias für bun --port
  • Der Standardwert von bun build --sourcemap wurde von inline source maps auf linked source maps geändert
    • Wenn das bisherige Verhalten benötigt wird, --sourcemap=inline verwenden

Performance-Verbesserungen

  • Bun 1.2 enthält Performance-Verbesserungen in mehreren Ausführungspfaden
    • node:http2: 2-mal schneller
    • S3-Uploads über node:http: 5-mal schneller
    • path.resolve(): 30-mal schneller
    • DNS resolution bei fetch(): 2-mal schneller
    • bun --hot: halbierter Speicherverbrauch
    • macOS fs.readdirSync(): Lesen kleiner Verzeichnisse 5 % schneller
    • String.at(): 44 % schneller
    • atob() mit großen String-Eingaben: bis zu 8-mal schneller
    • Dekomprimierung von gzip-Daten bei fetch(): 30 % schneller
    • Buffer.from(string, "base64") mit großen Eingaben: 6- bis 30-mal schneller
    • JSON.parse() mit großen String-Eingaben: 2- bis 4-mal schneller, bei object-Eingaben 6 % schneller
    • Durchsatz einiger Bun.serve()-Anwendungen: bis zu 2-mal höher
    • Error.captureStackTrace(): 9-mal schneller
    • fs.readFile() bei kleinen Dateien: bis zu 10 % schneller
    • console.log() mit String-Argumenten: 50 % schneller
  • Unter Windows wurde der JIT von JavaScriptCore aktiviert
    • Zuvor war der JIT nur unter macOS und Linux verfügbar
    • JavaScript wird unter Windows insgesamt schneller ausgeführt
    • Beispielsweise ist Object.entries() 20 % und Array.map() 50 % schneller

Installation und Upgrade

  • Neue Installationsbefehle
    • curl -fsSL https://bun.sh/install | bash
    • powershell -c "irm bun.sh/install.ps1 | iex"
    • npm install -g bun
    • Nach brew tap oven-sh/bun dann brew install bun
    • docker pull oven/bun
  • Eine bereits installierte Bun-Version wird mit bun upgrade aktualisiert

1 Kommentare

 
GN⁺ 2025-01-25
Meinungen auf Hacker News
  • Ich verstehe nicht, warum man Datenbanken von Drittanbietern und externe S3-Bibliotheken in die Core-/Standardbibliothek aufnimmt.
    Für so etwas wären optionale Bibliotheken doch besser, und eine solche Runtime sollte sehr sorgfältig auswählen, was in die Standardbibliothek kommt.
    Schon jetzt wirkt das Projekt, als wolle es wie eine Küchenspüle einfach alles aufnehmen.

    • Ich glaube, genau diese Haltung ist einer der Gründe, warum Bun Aufmerksamkeit bekommen hat.
      Der Ansatz „Batterien inklusive“ ist an vielen Stellen beliebt und ein häufig gewählter Weg.
      TypeScript-Konfiguration ist schwierig, und Webpack, S3, Postgres, Jest usw. sind es ebenfalls; deshalb ist auch ein vereinfachter Zugriff auf Dateien und Streams ziemlich interessant.
      Man wird sehen müssen, wie Anbieter für verteiltes Deployment darauf reagieren.
    • Soweit ich weiß, ist Bun VC-finanziert und muss irgendwann Geld verdienen; daher vermute ich, dass man es zu einem All-in-one-Runner machen will, um auf irgendeine Weise Vendor Lock-in zu erzeugen.
      Natürlich kann ich mich irren, aber solche Abhängigkeiten in die Core-/Standardbibliothek zu stecken, ergibt tatsächlich nicht besonders viel Sinn.
    • Viele Leute haben Jared, dem Autor von Bun, dasselbe gesagt, aber Jareds Ansicht ist, dass Bun alles mitbringen sollte, was ein Basisprojekt braucht.
      Er scheint zu glauben, dass Dinge im Core stärker optimiert werden können als Bibliotheken von Drittanbietern.
      Persönlich halte ich das für den falschen Ansatz und habe das Gefühl, dass Jared zu ambitioniert geworden ist, aber am Ende ist es eben sein Leidenschaftsprojekt.
    • Ich stimme völlig zu, dass optionale Bibliotheken besser wären.
      Bun formuliert es so: „Bun strebt eine Cloud-first-JavaScript-Runtime an. Das heißt, es unterstützt alle Tools und Services, die nötig sind, um Produktionsanwendungen in der Cloud auszuführen“ – aber das schafft bei mir nicht gerade Vertrauen.
      Diese konkrete Designentscheidung wirkt sogar schlechter als bei Node.
    • Das ist für Buns Managed-Service-Angebot gedacht.
      Das Problem mit VC-gestützter Software war immer, dass solche Integrationen versuchen, etwas Eigenes zu bieten – anders gesagt: Abhängigkeiten zu schaffen.
  • Meine Erfahrung mit Bun war bisher sehr gut.
    Bei neuen Projekten habe ich mich wegen ständig irgendwo brechender Änderungen immer davor gedrückt, TypeScript/Jest/React/Webpack einzurichten; bei Bun wird das intern gelöst und funktioniert für meine Anwendungsfälle einfach schmerzfrei.
    Zu Integrationen von Drittanbieter-Bibliotheken wie S3 oder SQL kann ich schwer etwas sagen, aber zumindest scheint der Fokus auf den am häufigsten genutzten und meistgefragten Dingen zu liegen.
    Ich finde gut, dass es dem Node.js-Tool-Ökosystem die nötige Vernunft zurückbringt.

    • Mich würde interessieren, welchen Unterschied Bun in dem oben genannten Frontend-Technology-Stack macht.
    • React-/TypeScript-Projekte ließen sich auch mit Vite oder Next.js gut einrichten.
      Ich glaube, hier wird unterschätzt, wie stark sich auch andere Tools inzwischen weiterentwickelt haben.
    • Bun ist großartig.
      Für mich ist es so etwas wie ein Produktivitäts-Cheatcode.
      Es gibt zwar einen kleinen Produktivitätsverlust, weil ChatGPT Bun nicht gut kennt, aber ich mag Bun trotzdem.
  • Es gibt viel Gutes, aber ich mache mir Sorgen, ob einige Standardverhalten nicht zu sehr in Richtung magisch verstecktes Verhalten gehen.
    Wenn man new Response(s3.file(...)) verwendet, lädt Bun die S3-Datei nicht auf den Server herunter und sendet sie an den Nutzer, sondern leitet den Nutzer auf eine vorab signierte URL der S3-Datei um.
    Als Default ist das eine ziemlich überraschende Wahl, und es ist überhaupt nicht klar, wie man das abschaltet, wenn man den S3-Bucket nicht direkt offenlegen möchte.

    • Ich respektiere den Bereich, den Bun erschließen will, aber wenn man dem Entwickler auf Twitter folgt, wirken die Entscheidungen stark auf kurzfristige Ergebnisse und Bequemlichkeit ausgerichtet, während die tiefgreifenden Auswirkungen dieses magischen Verhaltens eher leichtfertig behandelt werden.
      Anfangs hatte ich Erwartungen an dieses Projekt, aber angesichts der sporadisch öffentlich werdenden und für mich oft fragwürdigen Designentscheidungen in den sozialen Medien habe ich kein Vertrauen in die langfristige Richtung.
      Wenn es bei v0.x geblieben wäre, wäre das in Ordnung gewesen; aber nach einer 1.0 hätte die Messlatte für die Erweiterung der API-Oberfläche deutlich höher liegen müssen.
    • Man kann einfach einen Stream an die Response übergeben.
      Response(file.stream())
    • Ich verstehe, warum sie es so gemacht haben, aber dieses Design gefällt mir nicht.
      Für mich fühlt es sich wie ein stark nebenwirkungsbehaftetes Verhalten an, und beim Lesen sieht es so aus, als würde nicht eine URL, sondern der Dateiinhalt zurückgegeben.
      Trotzdem interessiert mich, was genau an der Offenlegung des Buckets stört.
      Es ist ja eine vorab signierte URL, also gewährt sie keinen breiten Zugriff.
      Eine explizite API wie Response((file(...).getPresignedURL())) wäre besser gewesen, oder eine Option, dieses Verhalten per Umgebungsvariable oder Bun-Konfiguration zu aktivieren.
  • Batteries included macht einen großen Unterschied
    Genau deshalb gefällt mir auch, dass Web-APIs wie Fetch API, Service Workers, Web Components, ES6+ und WebRTC inzwischen sowohl in V8- als auch in WebKit-Runtimes nativ sind
    Allerdings braucht es Maß und Ziel
    S3 könnte zu weit gehen, aber SQL-Treiber ergeben Sinn
    Trotzdem stellt sich die Frage, wo man die Grenze zieht
    Es gibt sehr viele Datenbanken; sollte man für die Hälfte davon Treiber einbauen?
    Schon auf diesem Niveau käme viel zusätzlicher Code dazu, was die ausführbare Datei verlangsamen könnte
    Außerdem kann man bei einer so sensiblen API in Bun auch Sicherheit übersehen
    Stell dir vor, irgendein Skript oder ein Pfadproblem führt dazu, dass eval ausgeführt wird und Bun die gesamte Quelldatei in ein privates S3 hochlädt – dann ist es vorbei

    • Ich frage mich, ob „mehr zusätzlicher Code verlangsamt die ausführbare Datei“ wirklich stimmt
      Je nachdem, wie Code zur Laufzeit geladen wird, könnte das meiner Ansicht nach fast vernachlässigbar sein
      Wenn das Laden von Code nur dann ausgelöst wird, wenn eine import-Anweisung auftaucht, gibt es dann nicht praktisch keinen Geschwindigkeits-Overhead?
      Selbst wenn statisch gelinkt wird, verstehe ich nicht ganz, warum die bloße Existenz von Code die ausführbare Datei in nennenswertem Maß verlangsamen sollte
      Die ausführbare Datei, die in den Speicher geladen werden muss, ist dann zwar buchstäblich größer, aber eine spürbare Verlangsamung dürfte das nicht sein
    • Vor einiger Zeit gab es auf HN eine Diskussion darüber, warum Browser SQLite nicht als First-Class-Funktion unterstützen; diese Argumente könnten auch auf Bun zutreffen
      Im Kern geht es darum, wer die Verantwortung für die Wartung der Bibliothek trägt und wie diese Bibliothek geändert wird, wenn sich SQLite ändert
      Wenn es in SQLite einen Bug gibt, wie wird er in Bun behoben?
      In welche Versionen müssen die Fixes einfließen?
      Ein Patch der Runtime kann das Verhalten des darauf laufenden Codes ändern; wie geht man damit um, wenn Nutzer Workarounds für das bisherige Verhalten eingebaut haben?
      Bis zu einem gewissen Grad sind das lösbare Probleme, aber sie bringen auch Nachteile mit sich
      Ab einem bestimmten Punkt ist es keine Runtime mehr, sondern eine Plattform, und damit kommen andere Verantwortlichkeiten und Probleme
    • Das Argument für die Aufnahme von S3 liegt meiner Ansicht nach darin, dass es viele Object-Storage-Dienste gibt, die eine S3-kompatible API implementieren
      Es ist zwar kein echter Webstandard, aber etwas, worauf sich viele Leute faktisch wie auf einen Standard einstellen
    • Zwar heißt es „mehr zusätzlicher Code verlangsamt die ausführbare Datei“, aber im Artikel gibt es buchstäblich Benchmarks, und dort steht, dass Bun doppelt so schnell ist wie die schnellste Node.js-Lösung
  • Ein Kunde setzt Bun seit Kurzem in Produktion ein
    Ich habe gehört, dass die Developer Experience von Bun wegen Geschwindigkeit und Einfachheit absurd gut ist
    Developer Experience spielt langfristig eine große Rolle
    Wenn Codebasis oder Prozesse ein Chaos sind, verliert man gute Leute, sofern man keine FAANG-ähnliche Vergütung zahlt

  • Ich habe Bun noch nicht ausprobiert, aber die Feature-Liste ist so lang, dass ich skeptisch bin, ob alles davon robust und fehlerfrei ist
    Ich hoffe, ich liege falsch, und will es in einem späteren Projekt einmal laufen lassen
    Aus Projektmanagement-Sicht bin ich etwas verwirrt, warum man Zeit in S3-Support steckt, obwohl noch nicht einmal 100 % Node.js-kompatibel ist
    Next.js ist ein sehr großes Ökosystem; wenn man Next.js-Kunden gewinnen kann, lässt sich damit deutlich stärker wachsen als mit S3-Support

    • 100 % Kompatibilität ist ein schöner Marketing-Sieg, aber die Long-Tail-Kompatibilität macht für Durchschnittsnutzer möglicherweise kaum einen Unterschied
      Wie viel der gesamten Node.js-API-Oberfläche nutzt man im Alltag tatsächlich?
      Und wie sehr verlässt man sich wirklich auf die seltsamen Edge Cases darin?
    • Die Formulierung „aus Projektmanagement-Sicht“ setzt voraus, dass man weiß, was das Projekt ist
      Die Leute, die daran arbeiten, sind auch keine Roboter
      Manche Aufgaben brauchen Zeit, bis man sie verstanden hat, und währenddessen kann man an anderen Dingen arbeiten
      Es macht auch nicht eine einzige Person alles
      „Mit Next.js-Kunden wächst man stärker“ – aber Wachstum in Richtung was?
      Das bringt kein Geld
      Das hier ist ein VC-finanziertes Projekt, und das Ziel ist nicht, Bun kostenlos bereitzustellen, um alle Nutzer weltweit zu gewinnen
    • Dass die lange Feature-Liste komplett robust und fehlerfrei sein soll, bezweifle ich besonders wegen des Punkts, dass es in Zig geschrieben ist
      Zig hat eine sehr geringe Speichersicherheit
      Wenn man auf eine Variable verweist, die nicht mehr lebt, greift man statt eines Segmentation Fault auf beliebigen, nicht zusammenhängenden Speicher zu
      Angeblich sogar im Debug- und Safe-Modus[0]
      Ist es wirklich so schwer, darüber ein Memory-Liveness-System zu legen, das Variablennamen als tot markiert und den Zugriff verhindert, wenn sie tot sind?
      Am Ende heißt es dann: „Verwende kein undefiniertes Verhalten“[1]
      Deshalb möchte ich nichts, was in Zig geschrieben ist, als dem Internet ausgesetzten Webserver betreiben
      [0] : https://news.ycombinator.com/item?id=41720995
      [1] : https://github.com/ziglang/zig/issues/16467#issuecomment-164...
    • Es ist weder besonders robust noch fehlerfrei
      Ich habe es letztes Jahr ausprobiert, und es ist ständig abgestürzt
    • Der Punkt, dass ein Bug behoben wurde, bei dem bun add Leerzeichen und Einrückungen in package.json nicht beibehalten hat, und dass es jetzt selbst die seltsamste Einrückung bewahrt, ist ziemlich lustig
      Ich weiß nicht, wer so etwas gefordert hat und warum man es für lohnend hielt, dafür Code zu schreiben
  • HTML-Imports sind großartig und cool
    Mit Unterstützung für HTML-Imports in Bun 1.2 soll sich die gesamte Frontend-Toolchain durch eine einzige import-Anweisung ersetzen lassen
    Man kann loslegen, indem man den HTML-Import an die Option static von Bun.serve übergibt

    import homepage from "./index.html";
    
    Bun.serve({  
      static: {  
        "/": homepage,  
      },
    
      async fetch(req) {  
        // ... api requests  
      },  
    });  
    
    • Ich frage mich, wie das zum Beispiel Vite ersetzen soll
      Sind Hot Module Replacement, CSS-Preprocessing und das Laden framework-spezifischer Plugins wie des Vue-SFC-Compilers möglich?
      Das Serven statischer Dateien ist ja nichts wirklich Neues, also übersehe ich vermutlich etwas
  • Ich dachte, es gebe kaum ein Projekt, dessen Scheitern so vorprogrammiert sei wie bei einer Konkurrenzalternative zu Node.js, aber es war gut, es einmal ausprobiert zu haben.
    Ich musste viele eigenständige Skripte erstellen, die Updates an Textdateien und SQLite-Datenbanken verarbeiten, und konnte TypeScript, bun:sqlite [1] und bun $ Shell [2] direkt nutzen, ohne Konfigurationsdateien oder die Verwaltung lokaler npm-Abhängigkeiten.
    Danach habe ich es auch in neuen JS-/TypeScript-Projekten ausprobiert; der eingebaute Bundler [3] und die Test-Unterstützung [4] kamen ebenfalls zum Einsatz, und die Installation der Abhängigkeiten war sofort erledigt.
    Dass alles schnell und sofort funktioniert, ist im Alltag eine echte Verbesserung der Lebensqualität, und inzwischen ist Bun meine erste Wahl für neue JS-Projekte.
    [1] https://bun.sh/docs/runtime/shell
    [2] https://bun.sh/docs/api/sqlite
    [3] https://bun.sh/docs/bundler
    [4] https://bun.sh/docs/cli/test

    • Geht mir genauso.
      Ich war auch auf der Linie: „Diese Dinge werden nächstes Jahr sowieso alle in npm landen, also was soll das bringen?“
      Am Ende habe ich Bun ausprobiert und war wirklich überrascht.
      Wenn sich die kleinen Details der Developer Experience summieren, macht das einen großen Unterschied.
      In meinen Projekten fühlt sich Bun wirklich wie die nächste Generation an.
  • Ich habe Bun vor Kurzem zum ersten Mal ausprobiert, und die Erfahrung war großartig.
    Für all meine Projekte ist Webpack oder Vite eingerichtet, um TypeScript zu verwenden; wenn es einmal konfiguriert ist, funktioniert es fast perfekt, aber die Einrichtung selbst ist mühsam und lohnt sich für kleine Skripte nicht.
    Bun dagegen funktionierte sofort.
    Um TS auf der CLI „direkt“ auszuführen, habe ich 10 bis 30 Minuten mit irgendeinem Tool wie node-ts oder so herumprobiert, mich mit schrecklichen Meldungen wie „kein Modul“, „import/require kann nicht verwendet werden“ und „ESM/CJS“ herumgeschlagen und alle üblichen Fixes versucht: den Modultyp in package.json ändern, tsconfig anpassen und zwischen import/require wechseln.
    Als letzten Ausweg habe ich für ein etwa 200 Zeilen langes Skript auf Bun gewechselt, und es funktionierte hervorragend.

    • Aktuelles Node.js unterstützt für solche Fälle inzwischen ebenfalls „TS einfach ausführen“.
      node --experimental-strip-types index.ts
      Wenn man kein aktuelles Node nutzt, hat das Paket tsx bei mir gut funktioniert.
      Es war besser als ts-node.
      Allerdings verwerfen beide Optionen die Typinformationen einfach, und Bun macht das genauso.
  • Mir gefällt die Richtung.
    Besonders die Aufnahme von nativer Unterstützung für S3 und Postgres ist sehr sinnvoll, weil sie eine brauchbare Alternative zum heutigen Zustand bietet, in dem man sich sein Framework selbst zusammensteckt.
    In allen Web-Frameworks wie Rails und Laravel ist das Standard, und das JS-Ökosystem kann davon stark profitieren.
    Als nächsten Schritt sehe ich Migrationen und Schema-Management sowie eine bessere Standard-Testerfahrung, mit der man Factory-Setups gut handhaben kann.