1 points par GN⁺ 2025-01-25 | 1 commentaires | Partager sur WhatsApp
  • Bun 1.2 est une version majeure visant un outil de développement JavaScript/TypeScript full-stack, avec une compatibilité Node.js renforcée et l’extension conjointe du runtime, du bundler, des tests et du gestionnaire de paquets
  • La validation de compatibilité a été renforcée en exécutant la suite de tests Node.js à chaque modification, avec l’ajout du support de node:http2, node:dgram, node:cluster, node:zlib et node:v8
  • Les nouvelles API intégrées Bun.s3 et Bun.sql intègrent l’accès au stockage d’objets compatible S3 et à Postgres directement dans le runtime, réduisant la dépendance à des clients externes
  • Le gestionnaire de paquets remplace le lockfile binaire bun.lockb par bun.lock au format JSONC, et ajoute .npmrc, bun publish, bun patch, bun outdated et bun run --filter
  • Des changements touchent le répertoire de travail de bun run, la gestion des échecs de Bun.build(), la valeur de retour de server.stop(), bun -p et les valeurs par défaut des sourcemaps ; les projets existants doivent donc vérifier l’impact de migration

Compatibilité Node.js renforcée

  • Bun 1.2 modifie son processus d’amélioration de la compatibilité en exécutant la suite de tests Node.js à chaque changement dans Bun
    • Auparavant, les bugs étaient corrigés principalement à partir des issues GitHub ou des signalements d’échec à l’exécution de paquets npm, mais cette approche relevait davantage du « whack-a-mole », rendant les gros refactorings difficiles
    • Des milliers de fichiers de test du dépôt Node.js ont été portés vers Bun, puis exécutés à chaque commit pour vérifier la compatibilité
  • Certains tests Node.js vérifient des détails d’implémentation internes et des messages d’erreur exacts ; Bun remplace donc, dans certains cas, les liaisons internes par ses propres stubs ou adapte les vérifications pour se concentrer sur name et code
    • Bun cherche autant que possible à reproduire les messages d’erreur de Node.js, mais peut parfois fournir un message plus utile tant que name et code restent identiques
  • Nouveaux modules et fonctionnalités Node.js pris en charge
    • node:http2 : prise en charge de la création de serveurs HTTP/2, nécessaire aussi pour les serveurs gRPC
    • node:dgram : prise en charge du bind/connect des sockets UDP
    • node:cluster : possibilité d’exécuter plusieurs instances de Bun pour répartir la charge sur plusieurs cœurs CPU
    • node:zlib : l’implémentation JavaScript a été réécrite en code natif et devient 2 fois plus rapide que dans Bun 1.1
    • node:v8 : getHeapSnapshot et writeHeapSnapshot permettent d’inspecter le tas de Bun dans Chrome DevTools
  • Le serveur node:http2 est 2 fois plus rapide que Node.js dans Bun 1.2
  • express traite les requêtes HTTP jusqu’à 3 fois plus vite que Node.js grâce aux améliorations de compatibilité node:http et aux optimisations du serveur HTTP de Bun
  • La prise en charge des extensions C++ utilisant l’API C++ de V8 a aussi été ajoutée
    • Node.js utilise V8, tandis que Bun repose sur JavaScriptCore, ce qui rend l’implémentation difficile
    • Bun implémente l’API C++ publique de V8 au-dessus de JavaScriptCore afin de faire fonctionner des paquets comme cpu-features
    • Cette prise en charge de l’API C++ de V8 étant complexe, il peut encore manquer des fonctionnalités pour la plupart des paquets ; le support de paquets comme node-canvas@v2 et node-sqlite3 continue d’être amélioré

API S3 intégrée Bun.s3

  • Bun 1.2 ajoute l’API intégrée Bun.s3 pour manipuler un stockage d’objets compatible S3
    • Elle peut être utilisée avec Amazon S3, Google Cloud Storage, Cloudflare R2 et d’autres services implémentant l’API S3
    • La lecture, l’écriture et la suppression de fichiers passent par une API compatible avec le standard Web Blob
  • s3.file() renvoie une référence différée à un fichier S3, utilisable comme l’API File de Bun avec text(), json(), arrayBuffer() ou stream()
  • Le client S3 de Bun est écrit en code natif, et non en JavaScript
    • Par rapport à l’utilisation de @aws-sdk/client-s3 dans Node.js, le téléchargement de fichiers depuis un bucket S3 est 5 fois plus rapide
  • Les fonctions d’écriture fournissent write() et writer()
    • write() permet d’envoyer des chaînes, Uint8Array, Blob, Response, etc.
    • writer() effectue des uploads multipart pour les gros fichiers
  • presign() génère une URL présignée autorisant l’envoi d’un fichier spécifique
    • Cela permet aux utilisateurs d’uploader directement vers S3 sans exposer d’identifiants ni accorder des permissions inutiles sur le bucket
  • Avec Bun.serve(), new Response(s3.file(...)) redirige vers une URL présignée au lieu de télécharger le fichier S3 puis de le renvoyer depuis le serveur
    • Cela réduit l’usage mémoire, le temps de traitement et les coûts de bande passante liés au téléchargement côté serveur
  • Les URL s3:// peuvent aussi être utilisées avec Bun.file() et fetch()
    • fetch("s3://...") permet d’uploader, de télécharger et de supprimer
    • Le S3Client par défaut se configure via des variables d’environnement comme AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY

Client Postgres intégré Bun.sql

  • Bun 1.2 ajoute Bun.sql, un client SQL intégré prenant en charge Postgres
    • Bun proposait déjà un client SQLite intégré, et cette version élargit la prise en charge des bases de données SQL
    • Une pull request existe aussi pour ajouter la prise en charge de MySQL
  • Bun.sql exécute le SQL via un tagged-template literal
    • Les valeurs JavaScript peuvent être transmises comme paramètres SQL
    • L’échappement des chaînes et les prepared statements sont utilisés automatiquement pour prévenir les injections SQL
  • Les résultats sont renvoyés sous forme de tableau d’objets utilisant les noms de colonnes comme clés
  • L’implémentation s’appuie sur du code natif et sur plusieurs optimisations
    • prepared statements automatiques
    • pipelining des requêtes
    • protocole wire binaire
    • pooling de connexions
    • mise en cache des structures
  • La lecture des lignes est jusqu’à 50 % plus rapide que lorsqu’on utilise des clients Postgres populaires dans Node.js
  • L’API s’inspire de postgres.js et a été conçue pour faciliter la migration du code existant vers le client SQL intégré de Bun

Évolutions du gestionnaire de paquets

  • Bun 1.2 remplace le lockfile par défaut, passant du binaire bun.lockb au fichier texte bun.lock
    • bun.lockb a contribué à rendre bun install presque 30 fois plus rapide que npm, mais son contenu était difficile à consulter sur GitHub, ce qui compliquait la revue des pull requests et la résolution des conflits de fusion
    • Les outils comme Dependabot avaient aussi du mal à lire le lockfile
  • bun.lock est un fichier JSONC
    • Il prend en charge les commentaires et les trailing commas
    • Il facilite la lecture des diff de pull request, et les trailing commas réduisent les risques de conflits de fusion
  • Les nouveaux projets créent un bun.lock
    • Les projets existants avec bun.lockb continuent à prendre en charge le lockfile binaire sans migration automatique
    • bun.lockb restera pris en charge sur le long terme, et bun add comme bun update continueront à le mettre à jour
    • Il est possible de migrer vers le nouveau lockfile texte avec bun install --save-text-lockfile
  • bun install est 30 % plus rapide que Bun 1.1, même après le passage au lockfile texte
  • Il est possible d’utiliser des commentaires et des trailing commas dans package.json
    • require() et import() peuvent aussi lire ce type de package.json
    • Comme cette fonctionnalité n’est pas largement prise en charge dans l’ensemble de l’écosystème JavaScript, il est indiqué de l’utiliser « at your own risk »
  • La prise en charge de .npmrc a été ajoutée
    • Bun lit les fichiers .npmrc à la racine du projet et dans le répertoire personnel
    • Ils peuvent servir à configurer le registry, les scoped packages et l’authentification à un registry privé
  • Nouvelles commandes et nouvelles options pour le gestionnaire de paquets
    • bun run --filter : exécuter simultanément le même script dans plusieurs workspaces
    • bun outdated : vérifier les dépendances obsolètes
    • bun publish : remplaçant de npm publish, avec prise en charge de l’authentification .npmrc, du packaging en tarball, de l’OTP et des cas limites de package.json
    • bun patch : enregistrer les modifications apportées à une dépendance dans un fichier .patch sous patches/, puis les appliquer automatiquement lors de bun install
    • --omit=dev|optional|peer : exclure les dépendances dev, optional et peer de l’installation
    • Les certificats CA peuvent être configurés via bunfig.toml, des flags CLI ou .npmrc
    • La prise en charge de bundleDependencies et la conservation de l’indentation de package.json avec bun add ont aussi été ajoutées

Améliorations du test runner

  • bun test prend en charge le reporter JUnit XML
    • Avec bun test --reporter=junit --reporter-outfile=junit.xml, il est possible d’envoyer les résultats de test à des outils CI/CD comme Jenkins, CircleCI ou GitLab CI
    • Le reporting JUnit peut aussi être configuré dans bunfig.toml
  • Un reporter LCOV a été ajouté pour la couverture de code
    • bun test --coverage --coverage-reporter=lcov génère coverage/lcov.info
    • --coverage-dir permet de changer le répertoire de sortie
  • Les inline snapshots sont pris en charge via expect().toMatchInlineSnapshot()
    • bun test -u ou --update-snapshots met à jour les snapshots directement dans le fichier de test
    • toThrowErrorMatchingSnapshot() et toThrowErrorMatchingInlineSnapshot() sont également disponibles
  • test.only() fonctionne désormais sans le flag --only
  • L’API expect() ajoute des matchers présents dans Jest, Vitest et jest-extended
    • toContainValue(), toContainKey(), et la famille toHaveReturned()
    • Il est possible de passer un message d’erreur personnalisé en deuxième argument
  • jest.setTimeout() et setDefaultTimeout() permettent de modifier le timeout de test par défaut du scope courant ou du module

Bundler et fonctions de build

  • Bun 1.2 prend en charge les imports HTML
    • En passant un fichier HTML à l’option static de Bun.serve, Bun bundle automatiquement les balises <script> et <link> du HTML, puis les expose via des routes statiques
  • bun build --compile prend en charge la compilation croisée
    • Il est possible de créer des binaires Windows ou macOS depuis Linux, et inversement
    • Les builds Windows peuvent définir une icône et masquer la fenêtre de console
  • bun build --bytecode génère un cache de bytecode
    • Cela peut diviser par deux le temps de démarrage d’applications comme eslint
    • Les fichiers .jsc contiennent le cache de bytecode du fichier .js correspondant, et les deux sont nécessaires à l’exécution
    • Le cache de bytecode peut être 8 fois plus volumineux que le code source, ce qui améliore le temps de démarrage au prix d’un usage disque plus élevé
  • bun build --format=cjs permet de choisir le format de sortie CommonJS
    • Auparavant, seul ESM était pris en charge
    • Cela facilite la création de bibliothèques ou d’applications destinées à d’anciennes versions de Node.js
  • La détection de CommonJS a été améliorée
    • Quand un fichier est ambigu, la directive "use strict" en tête de fichier est utilisée comme ultime heuristique CommonJS
    • require.main === module est réécrit en import.meta.main, ce qui permet son usage avec des instructions import
  • L’API de plugins ajoute le hook onBeforeParse()
    • Il doit être implémenté non pas en JavaScript, mais sous forme d’addon N-API
    • Il permet de manipuler le code source juste avant le parsing avec un surcoût quasi nul dans des langages compilés comme Rust, C/C++ ou Zig
    • Il s’agit d’une API avancée destinée aux auteurs de plugins et de frameworks
  • Les options de build ont également été étendues
    • --env="PUBLIC_*" injecte des variables d’environnement dans le bundle
    • Suppression d’appels de fonctions avec --drop=console, par exemple
    • Ajout de banner/footer
    • Bun.embeddedFiles() permet de voir la liste des fichiers inclus dans un exécutable autonome
    • --ignore-dce-annotations permet d’ignorer des annotations de dead-code elimination incorrectes
    • --packages=external permet de ne pas inclure les dépendances de paquet dans le bundle

Bundling CSS

  • Bun 1.2 implémente un nouveau parseur et bundler CSS
    • Il est dérivé du travail de LightningCSS, réécrit de Rust vers Zig, puis intégré au parseur JavaScript/TypeScript, au bundler et au runtime de Bun
  • bun build ./index.css permet de combiner plusieurs fichiers CSS ainsi que les références @import, url et @font-face en un seul fichier CSS
  • Il est possible d’importer des fichiers .css depuis du code JavaScript et TypeScript
    • Les CSS importés depuis le graphe de modules JavaScript, ainsi que les règles @import, sont aplatis en un seul fichier CSS par entrypoint
  • L’API Bun.build() permet aussi de bundler CSS et JavaScript via une même API

Ajouts à l’API runtime de Bun

  • Bun.serve() prend en charge les routes statiques via la propriété static
    • le chemin est passé comme clé, et l’objet Response comme valeur
    • les routes statiques sont jusqu’à 40 % plus rapides qu’un traitement direct dans le handler fetch()
    • le body de la réponse, les headers et le code de statut sont mis en cache en mémoire, ce qui évite les allocations JavaScript et le garbage collection
    • server.reload() permet de recharger les routes statiques
  • Bun.udpSocket() fournit des sockets UDP au format de l’API Bun
    • node:dgram est aussi pris en charge, mais Bun.udpSocket() propose une API moderne proche de Bun.listen()
    • il peut envoyer plusieurs datagrammes UDP avec un seul syscall et gère la backpressure de l’OS
  • Bun.file() prend en charge delete(), unlink() et stat()
    • stat() renvoie des métadonnées au même format que l’objet Stats de fs.stat() de Node.js
    • la même API peut aussi être utilisée pour les fichiers S3
  • Bun.color() fournit le parsing, la normalisation et la conversion des couleurs
    • prend en charge CSS, les codes couleur ANSI, RGB, HSL, etc.
  • dns.prefetch() permet de précharger des enregistrements DNS pour réchauffer le cache DNS au démarrage
  • Autres utilitaires
    • Bun.inspect.table() : renvoie une chaîne au format tableau, comme console.table
    • Bun.randomUUIDv7() : génère un UUID v7 monotone adapté au tri et aux bases de données

Améliorations du client SQLite

  • Le client SQLite intégré à Bun peut mapper les résultats de requête vers des instances de classe avec query.as(Class)
    • il est possible d’y ajouter des getters, setters et méthodes
    • pour des raisons de performance, le constructor de classe, les initialiseurs par défaut et les champs privés ne sont pas pris en charge
    • ce n’est pas un ORM, car il ne gère ni les relations ni la génération de SQL
  • query.iterate() traite les lignes via un itérateur sans tout charger en mémoire d’un coup
    • l’objet de requête lui-même peut aussi être parcouru avec une boucle for
  • avec l’option strict, on peut omettre les préfixes $, @, : dans les paramètres de requête
    • une erreur est levée si un paramètre manque
  • le résultat de db.run() permet de vérifier le nombre de lignes modifiées et l’ID de la dernière ligne insérée
    • changes
    • lastInsertRowid
  • l’option safeIntegers renvoie les entiers 64 bits en BigInt au lieu de number tronqués
    • elle peut être définie au niveau de la base de données ou de la requête
  • la syntaxe JavaScript using permet de fermer automatiquement les statements et la base de données à la sortie du scope

Compiler et exécuter du C depuis JavaScript

  • Bun 1.2 ajoute une prise en charge expérimentale pour compiler et exécuter du C depuis JavaScript
    • cela passe par l’API cc() de bun:ffi
    • cela permet d’utiliser des bibliothèques système en C depuis JavaScript sans étape de build séparée
  • Bun embarque tinycc
    • contrairement à gcc ou clang, il peut compiler du code C simple en quelques millisecondes
    • le code C peut ainsi être compilé et exécuté à la demande
  • du code C utilisant N-API est également pris en charge
    • il fonctionne avec Bun seul, sans étape de build node-gyp

Prise en charge de musl et d’Alpine Linux

  • Bun 1.2 ajoute des builds Bun pour les distributions Linux utilisant musl libc au lieu de glibc
    • ils peuvent être utilisés dans des environnements comme Alpine Linux
    • Linux x64 et aarch64 sont pris en charge
  • dans Docker, il est possible d’utiliser l’image oven/bun:alpine
  • musl permet des images de conteneur plus petites, mais a tendance à être légèrement plus lent que la version glibc de Bun
    • sauf raison particulière, il est recommandé d’utiliser glibc

Fonctionnalités du langage JavaScript

  • prise en charge des import attributes
    • il est possible d’importer explicitement du JSON, du texte, du TOML, etc., comme dans import json from "./package.json" with { type: "json" }
    • cela fonctionne aussi avec import() dynamique
  • prise en charge de using et await using
    • à la sortie du scope, [Symbol.dispose] ou [Symbol.asyncDispose] est appelé pour libérer automatiquement les ressources
    • cette prise en charge existe dans plusieurs API Bun, dont Bun.spawn(), Bun.serve(), Bun.connect(), Bun.listen(), bun:sqlite, etc.
  • Nouvelles API liées aux promesses
    • Promise.withResolvers() : crée promise, resolve et reject en une fois
    • Promise.try() : encapsule une fonction synchrone ou asynchrone dans une promise
  • API liées aux erreurs et aux tableaux d’octets
    • Error.isError() : vérifie plus précisément s’il s’agit d’une Error, même en cas de manipulation de la prototype chain ou de contexte cross-realm via node:vm
    • Uint8Array.toBase64() / Uint8Array.fromBase64()
    • Uint8Array.toHex() / Uint8Array.fromHex()
  • ajout des iterator helpers
    • map, flatMap, filter, take, drop, reduce, toArray, forEach, find
  • prise en charge de Float16Array
    • les tableaux à virgule flottante 16 bits sont moins précis que les 32 bits, mais plus économes en mémoire

Ajouts aux Web API

  • prise en charge de TextDecoderStream et TextEncoderStream
    • il s’agit des versions streaming de TextDecoder et TextEncoder
    • dans Bun, TextEncoderStream est jusqu’à 30 fois plus rapide que dans Node.js
  • prise en charge de l’option stream de TextDecoder
    • même si un chunk ne contient pas un point de code UTF-8 complet, il peut être traité comme partie d’un flux plus large
  • ajout de la méthode bytes()
    • elle renvoie les données de flux sous forme de Uint8Array depuis Response, Blob, Bun.file(), etc.
    • cela réduit l’étape consistant à créer un Uint8Array après arrayBuffer()
  • prise en charge de l’upload fetch() en streaming
    • utile pour les gros fichiers ou les flux de données dont la longueur de contenu n’est pas connue à l’avance
  • implémentation de console.group() et console.groupEnd()
  • prise en charge de URL.createObjectURL()
    • permet de créer une URL depuis un Blob et de l’utiliser avec fetch(), Worker et import()
    • les scripts Worker passent aussi par le transpileur de Bun, donc la syntaxe TypeScript peut être utilisée
  • AbortSignal.any() permet de combiner plusieurs AbortSignal pour que si l’un est annulé, le signal parent le soit aussi

Changements de comportement et points d’attention pour la migration

  • Le répertoire de travail de bun run change
    • auparavant, il utilisait le répertoire de travail courant du shell
    • dans Bun 1.2, il utilise le répertoire parent de package.json comme répertoire de travail du script
    • ce changement vise à aligner le comportement sur celui de npm et yarn
  • bun test signale désormais comme échec les uncaught errors ou rejections survenant entre les tests
    • auparavant, ces erreurs pouvaient ne pas être traitées comme des échecs de test
  • server.stop() renvoie désormais un Promise<void>
    • cela permet d’attendre la fermeture des connexions HTTP en cours
  • Bun.build() rejette désormais en cas d’échec, au lieu d’ajouter l’erreur dans logs d’un résultat résolu
    • si l’ancien comportement est nécessaire, vous pouvez définir throw: false
  • bun -p devient un alias de bun --print, pour s’aligner sur Node.js
    • auparavant, c’était un alias de bun --port
  • la valeur par défaut de bun build --sourcemap passe des source maps inline aux source maps liées
    • si l’ancien comportement est nécessaire, utilisez --sourcemap=inline

Améliorations des performances

  • Bun 1.2 inclut des améliorations de performances sur plusieurs chemins d’exécution
    • node:http2 : 2x plus rapide
    • upload S3 via node:http : 5x plus rapide
    • path.resolve() : 30x plus rapide
    • résolution DNS de fetch() : 2x plus rapide
    • bun --hot : utilisation mémoire réduite de moitié
    • fs.readdirSync() sur macOS : lecture des petits répertoires 5 % plus rapide
    • String.at() : 44 % plus rapide
    • atob() sur de grandes chaînes en entrée : jusqu’à 8x plus rapide
    • décompression des données gzip avec fetch() : 30 % plus rapide
    • Buffer.from(string, "base64") sur de grandes entrées : 6x à 30x plus rapide
    • JSON.parse() sur de grandes chaînes en entrée : 2x à 4x plus rapide, et 6 % plus rapide pour les entrées de type object
    • débit de certaines applications Bun.serve() : jusqu’à 2x plus élevé
    • Error.captureStackTrace() : 9x plus rapide
    • fs.readFile() sur de petits fichiers : jusqu’à 10 % plus rapide
    • console.log() avec des arguments de type chaîne : 50 % plus rapide
  • Sous Windows, le JIT de JavaScriptCore est activé
    • auparavant, le JIT n’était disponible que sur macOS et Linux
    • JavaScript s’exécute globalement plus vite sous Windows
    • par exemple, Object.entries() est 20 % plus rapide et Array.map() 50 % plus rapide

Installation et mise à niveau

  • Nouvelles commandes d’installation
    • curl -fsSL https://bun.sh/install | bash
    • powershell -c "irm bun.sh/install.ps1 | iex"
    • npm install -g bun
    • brew tap oven-sh/bun puis brew install bun
    • docker pull oven/bun
  • Si Bun est déjà installé, effectuez la mise à niveau avec bun upgrade

1 commentaires

 
GN⁺ 2025-01-25
Avis sur Hacker News
  • Je ne comprends pas pourquoi intégrer une base de données tierce et une bibliothèque S3 externe dans le cœur/la bibliothèque standard.
    Ce genre de chose serait mieux sous forme de bibliothèque optionnelle, et ce type de runtime devrait choisir avec beaucoup de prudence ce qu’il inclut dans sa bibliothèque standard.
    Ça donne déjà l’impression d’un projet qui met tout et n’importe quoi, façon évier de cuisine.

    • Je pense que cette position est justement l’une des raisons pour lesquelles Bun a attiré l’attention.
      L’approche batteries incluses est populaire dans beaucoup d’endroits et constitue une voie souvent choisie.
      La configuration de TypeScript est difficile, et c’est pareil pour Webpack, S3, Postgres, Jest, etc. ; l’accès simplifié aux fichiers et aux streams est aussi assez intéressant.
      Il faudra voir comment les fournisseurs de déploiement distribué se positionnent.
    • À ma connaissance, Bun a reçu des fonds de VC, donc il faudra bien qu’ils gagnent de l’argent un jour ; j’imagine donc qu’ils essaient peut-être d’en faire un exécuteur tout-en-un afin de créer une forme ou une autre de dépendance à un fournisseur.
      Je peux évidemment me tromper, mais mettre ce type de dépendances dans le cœur/la bibliothèque standard n’a pas vraiment de sens.
    • Beaucoup de gens ont dit la même chose à Jared, l’auteur de Bun, mais sa vision est que Bun doit inclure tout ce dont un projet de base a besoin.
      Il semble penser qu’en les mettant dans le cœur, il peut optimiser davantage qu’avec des bibliothèques tierces.
      Personnellement, je trouve que c’est une mauvaise approche et que Jared est devenu trop ambitieux, mais au final c’est son projet passion.
    • Je suis entièrement d’accord pour dire que des bibliothèques optionnelles seraient préférables.
      Dans les termes de Bun : « Bun vise à être un runtime JavaScript cloud-first. Autrement dit, il prend en charge tous les outils et services nécessaires pour exécuter des applications de production dans le cloud », mais cette phrase n’inspire pas vraiment confiance.
      Ce choix de conception précis semble encore pire que Node.
    • C’est destiné à l’offre de service managé de Bun.
      Le problème des logiciels financés par le VC a toujours été que ces intégrations cherchent à proposer quelque chose de propriétaire, autrement dit à créer une dépendance.
  • Jusqu’ici, mon expérience avec Bun a été excellente.
    Quand je configurais TypeScript/Jest/React/Webpack sur un nouveau projet, j’appréhendais toujours les changements cassants un peu partout ; avec Bun, c’est géré en interne et, pour mes usages, ça fonctionne simplement sans douleur.
    Difficile de me prononcer sur l’intégration de bibliothèques tierces comme S3 ou SQL, mais ils semblent au moins se concentrer sur les éléments les plus courants et les plus demandés.
    J’apprécie qu’il apporte une forme de normalité dont l’écosystème d’outils Node.js avait besoin.

    • Je suis curieux de savoir quelle différence Bun apporte à la stack frontend mentionnée plus haut.
    • J’ai toujours réussi à configurer correctement des projets React/TypeScript avec Vite ou Next.js.
      Tu sembles sous-estimer à quel point les autres outils ont aussi beaucoup progressé entre-temps.
    • Bun est excellent.
      Pour moi, c’est comme un code de triche pour la productivité.
      Il y a bien une petite perte de productivité parce que ChatGPT connaît mal Bun, mais j’aime quand même Bun.
  • Il y a beaucoup de bonnes choses, mais je m’inquiète de voir certains comportements par défaut devenir trop magiques et implicites.
    Si on utilise new Response(s3.file(...)), au lieu de télécharger le fichier S3 sur le serveur puis de l’envoyer à l’utilisateur, Bun redirige l’utilisateur vers l’URL présignée du fichier S3.
    Comme valeur par défaut, c’est un choix assez surprenant, et il n’est pas du tout évident de savoir comment le désactiver quand on ne veut pas exposer directement son bucket S3.

    • Je respecte le territoire que Bun essaie d’explorer, mais si l’on suit son créateur sur Twitter, on voit que les décisions penchent beaucoup vers les gains à court terme et la commodité, tandis que les implications profondes de ces comportements magiques sont traitées assez légèrement.
      Au début, ce projet me donnait envie d’y croire, mais à voir les décisions de conception sporadiques, rendues publiques sur les réseaux, et que je trouve souvent mauvaises, je n’ai pas confiance dans sa direction à long terme.
      S’ils étaient restés en v0.x, pourquoi pas, mais après une 1.0, le seuil pour élargir la surface d’API aurait dû être beaucoup plus élevé.
    • Il suffit de passer un stream à la réponse.
      Response(file.stream())
    • Je comprends pourquoi ils ont fait ça, mais je n’aime pas cette conception.
      Personnellement, ça me donne l’impression d’un comportement à fort effet de bord, et à la lecture on dirait que ça renvoie le contenu du fichier, pas une URL.
      Cela dit, je me demande aussi en quoi l’exposition du bucket est gênante.
      Comme il s’agit d’une URL présignée, elle ne donne pas non plus de droits d’accès étendus.
      Une API explicite comme Response((file(...).getPresignedURL())) aurait été préférable, ou bien une option permettant d’activer ce comportement via une variable d’environnement ou la configuration de Bun.
  • Batteries incluses fait une grande différence
    C’est aussi pour ça que j’aime le fait que les API Web comme Fetch API, les Service Workers, les Web Components, ES6+ ou WebRTC soient désormais natives à la fois dans les runtimes V8 et WebKit
    Il faut toutefois une limite
    S3 va peut-être trop loin, mais les pilotes SQL ont du sens
    Cela dit, la question reste de savoir jusqu’où aller
    Il existe énormément de bases de données : faut-il inclure les pilotes de la moitié d’entre elles ?
    Rien qu’à ce niveau, cela ferait beaucoup de code supplémentaire, ce qui pourrait ralentir l’exécutable
    Et intégrer des API aussi sensibles dans Bun pourrait aussi faire passer la sécurité au second plan
    Imaginez qu’un eval soit exécuté à cause d’un script ou d’un problème de chemin, et que Bun téléverse alors l’intégralité des fichiers source vers un S3 privé : à ce moment-là, c’est fini

    • Je me demande si « plus de code supplémentaire ralentit l’exécutable » est vraiment vrai
      J’ai vu que, selon la façon dont le code est chargé au runtime, cela pouvait être quasiment négligeable
      Si le chargement du code n’est déclenché que lorsqu’une instruction import apparaît, n’y a-t-il pas, en pratique, aucun surcoût en performance ?
      Même avec une liaison statique, je ne vois pas très bien pourquoi la simple présence du code ralentirait l’exécutable à un niveau significatif
      Il y a bien le fait que l’exécutable à charger en mémoire devient littéralement plus gros, mais je doute que cela se traduise par un ralentissement perceptible
    • Il y avait autrefois sur HN une discussion sur les raisons pour lesquelles les navigateurs ne prennent pas SQLite en charge comme citoyen de première classe, et cet argument peut aussi s’appliquer à Bun
      Le point central est de savoir qui est responsable de la maintenance de la bibliothèque, et comment cette bibliothèque doit évoluer lorsque SQLite change
      S’il y a un bug dans SQLite, comment le corrigera-t-on dans Bun ?
      Quelles versions doivent recevoir le correctif ?
      Un correctif du runtime peut changer le comportement du code qui tourne dessus : comment gérer les utilisateurs qui ont déjà contourné le problème en s’appuyant sur l’ancien comportement ?
      Ce sont des problèmes qu’on peut résoudre dans une certaine mesure, mais ils ont aussi des inconvénients
      À partir d’un certain point, on ne parle plus d’un runtime mais d’une plateforme, avec d’autres responsabilités et problèmes qui vont avec
    • Je pense que l’argument en faveur de l’intégration de S3 repose sur le fait qu’il existe beaucoup de services de stockage objet qui implémentent une API compatible S3
      Ce n’est pas un vrai standard du Web, mais beaucoup de gens le traitent de fait comme un standard auquel se conformer
    • On dit que « plus de code supplémentaire ralentit l’exécutable », mais l’article contient littéralement des benchmarks et indique que Bun est deux fois plus rapide que la solution Node.js la plus rapide
  • Un client récent utilise Bun en production
    J’ai entendu dire que, grâce à sa vitesse et sa simplicité, l’expérience de développement avec Bun est absurdement bonne
    L’expérience développeur joue un grand rôle sur le long terme
    Si votre base de code ou vos processus sont en désordre, vous perdrez les bons profils, sauf à leur offrir une rémunération de niveau FAANG

  • Je n’ai pas encore essayé Bun, mais la liste de fonctionnalités est tellement longue que je doute qu’elles soient toutes solides et sans bugs
    J’espère me tromper, et je compte l’essayer dans un futur projet
    Du point de vue de la gestion de projet, je suis un peu perplexe : pourquoi consacrer du temps au support de S3 alors que ce n’est même pas encore 100 % compatible Node.js ?
    Next.js est un très gros écosystème ; pouvoir attirer des clients Next.js permettrait de croître bien davantage que le support de S3

    • La compatibilité à 100 % est une belle victoire marketing, mais la compatibilité de longue traîne peut ne pas changer grand-chose pour l’utilisateur moyen
      Au quotidien, quelle part de toute la surface d’API Node.js utilisez-vous réellement ?
      Et dans quelle mesure dépendez-vous vraiment des cas limites bizarres qu’elle contient ?
    • Parler du « point de vue de la gestion de projet » suppose que l’on sait ce qu’est le projet
      Les personnes qui y travaillent ne sont pas des robots non plus
      Certaines tâches prennent du temps à comprendre, et pendant ce temps on peut faire autre chose
      Une seule personne ne fait pas tout
      On dit qu’« attirer des clients Next.js ferait davantage croître le projet », mais croître vers quoi ?
      Cela ne rapporte pas d’argent
      C’est un projet financé par du capital-risque, et l’objectif n’est pas de fournir Bun gratuitement pour gagner tous les utilisateurs du monde
    • Ce qui me gêne particulièrement dans cette longue liste de fonctionnalités dont je doute qu’elles soient toutes robustes et sans bugs, c’est le fait que ce soit écrit en Zig
      Zig offre très peu de sécurité mémoire
      Si vous référencez une variable qui n’est plus vivante, vous accédez à une zone mémoire arbitraire et sans rapport, au lieu d’obtenir une erreur de segmentation
      Apparemment, c’est aussi le cas en mode debug et en mode sécurisé[0]
      Est-ce si difficile d’ajouter par-dessus un système de durée de vie mémoire qui marque les noms de variables comme morts et empêche d’y accéder lorsqu’ils le sont ?
      Au final, cela revient à dire « n’utilisez pas de comportement indéfini »[1]
      C’est pourquoi je ne voudrais rien écrit en Zig sur un serveur Web exposé à Internet
      [0] : https://news.ycombinator.com/item?id=41720995
      [1] : https://github.com/ziglang/zig/issues/16467#issuecomment-164...
    • Ce n’est ni très robuste ni sans bugs
      Je l’ai essayé l’an dernier et il plantait sans arrêt
    • L’entrée disant qu’ils ont corrigé un bug où bun add ne préservait pas les espaces et l’indentation de package.json, et qu’il préserve désormais même les indentations les plus étranges, est assez drôle
      Je ne sais pas qui a demandé ça, ni pourquoi ils ont estimé que cela valait la peine d’y consacrer du code
  • L’import HTML est impressionnant et très cool
    Avec la prise en charge de l’import HTML dans Bun 1.2, ils disent pouvoir remplacer toute la chaîne d’outils frontend par une seule instruction import
    On peut commencer en passant un import HTML à l’option static de Bun.serve

    import homepage from "./index.html";
    
    Bun.serve({  
      static: {  
        "/": homepage,  
      },
    
      async fetch(req) {  
        // ... api requests  
      },  
    });  
    
    • Je me demande comment cela permet, par exemple, de remplacer Vite
      Est-ce que cela permet le remplacement de modules à chaud, le prétraitement CSS, ou le chargement de plugins propres aux frameworks comme le compilateur de SFC Vue ?
      Servir des fichiers statiques n’a rien de vraiment nouveau, donc j’ai l’impression de passer à côté de quelque chose
  • Je pensais qu’aucun projet n’était aussi voué à l’échec qu’une alternative concurrente à Node.js, mais j’ai bien fait de l’essayer
    Je devais créer beaucoup de scripts autonomes pour gérer des fichiers texte et mettre à jour une base SQLite, et j’ai pu utiliser TypeScript, bun:sqlite [1] et bun $ Shell [2] directement, sans fichier de configuration ni gestion de dépendances npm locales
    Je l’ai ensuite essayé sur de nouveaux projets JS/TypeScript, et le bundler intégré [3] ainsi que la prise en charge des tests [4] se sont aussi révélés utiles, tandis que l’installation des dépendances se termine instantanément
    Le fait que tout fonctionne rapidement et immédiatement améliore vraiment la qualité de vie, et Bun est désormais mon premier choix pour les nouveaux projets JS
    [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

    • Pareil pour moi
      J’étais plutôt du genre : « à quoi bon, tout ça arrivera aussi dans npm l’an prochain »
      J’ai fini par essayer Bun, et j’ai vraiment été surpris
      Quand les petits éléments de l’expérience développeur s’accumulent, la différence est énorme
      Dans mon projet, Bun donne vraiment l’impression d’être la génération suivante
  • J’ai essayé Bun pour la première fois il y a quelque temps, et l’expérience a été excellente
    Tous mes projets sont configurés avec Webpack ou Vite pour utiliser TypeScript, et une fois configuré, ça marche presque parfaitement, mais la configuration elle-même est pénible et n’en vaut pas la peine pour de petits scripts
    À l’inverse, Bun a fonctionné immédiatement
    Pour essayer d’exécuter du TS « directement » depuis la CLI, j’avais passé 10 à 30 minutes à bricoler avec un outil du genre node-ts ou je ne sais quoi, en affrontant des messages horribles comme « ce n’est pas un module », « impossible d’utiliser import/require », « ESM/CJS », et j’avais essayé toutes les corrections habituelles : changer le type de module dans package.json, modifier tsconfig, changer la manière d’utiliser import/require
    J’essayais d’exécuter un script d’environ 200 lignes ; en dernier recours je suis passé à Bun, et ça a fonctionné à merveille

    • Les versions récentes de Node.js prennent désormais aussi en charge, dans ce genre de cas, le fait de « simplement exécuter du TS »
      node --experimental-strip-types index.ts
      Si vous n’avez pas une version récente de Node, le paquet tsx a bien fonctionné pour moi
      Mieux que ts-node
      Cela dit, dans les deux cas, les informations de type sont simplement jetées, et c’est pareil avec Bun
  • J’aime la direction prise
    En particulier, l’ajout d’une prise en charge native de S3 et Postgres est très pertinent : cela peut constituer une alternative à l’état actuel où l’on « assemble soi-même son framework »
    Dans tous les frameworks web comme Rails et Laravel, c’est la norme, et l’écosystème JS peut en tirer un grand bénéfice
    À mon avis, la prochaine étape serait une meilleure expérience de test par défaut, avec une bonne gestion des migrations et des schémas, ainsi que de la configuration des factories