1 puntos por GN⁺ 2025-01-25 | 1 comentarios | Compartir por WhatsApp
  • Bun 1.2 es una gran versión orientada a ser una herramienta full-stack de desarrollo JavaScript/TypeScript, ampliando a la vez la compatibilidad con Node.js y el runtime, bundler, pruebas y gestor de paquetes
  • Reforzó la validación de compatibilidad ejecutando la suite de pruebas de Node.js en cada cambio, y añadió soporte para node:http2, node:dgram, node:cluster, node:zlib y node:v8
  • Las nuevas API integradas Bun.s3 y Bun.sql incorporan al runtime el acceso a almacenamiento de objetos compatible con S3 y a Postgres, reduciendo la dependencia de clientes externos
  • El gestor de paquetes cambia el lockfile predeterminado del binario bun.lockb al bun.lock basado en JSONC, y añade .npmrc, bun publish, bun patch, bun outdated y bun run --filter
  • Como cambiaron el directorio de trabajo de bun run, el manejo de fallos de Bun.build(), el valor de retorno de server.stop(), bun -p y el valor predeterminado de sourcemap, los proyectos existentes deben revisar el impacto de migración

Compatibilidad con Node.js reforzada

  • Bun 1.2 cambió su proceso de mejora de compatibilidad para ejecutar la suite de pruebas de Node.js en cada cambio de Bun
    • Antes corregía bugs principalmente a partir de issues en GitHub o reportes de fallos al ejecutar paquetes npm, pero ese método se parecía más a “jugar al topo” y dificultaba grandes refactorizaciones
    • Portó miles de archivos de prueba del repositorio de Node.js a Bun, y ejecuta esas pruebas en cada commit para verificar la compatibilidad
  • Como las pruebas de Node.js a veces validan detalles de implementación interna y mensajes de error exactos, Bun en algunas pruebas reemplazó bindings internos con stubs propios o ajustó la verificación para centrarse en name y code
    • Bun intenta igualar los mensajes de error de Node.js siempre que puede, pero en algunos casos ofrece mensajes más útiles si name y code son los mismos
  • Nuevos módulos y funciones de Node.js compatibles
    • node:http2: soporte para crear servidores HTTP/2, también necesario para servidores gRPC
    • node:dgram: soporte para bind/connect de sockets UDP
    • node:cluster: permite ejecutar varias instancias de Bun para distribuir trabajo entre varios núcleos de CPU
    • node:zlib: la implementación en JavaScript fue reescrita en código nativo y ahora es 2 veces más rápida que en Bun 1.1
    • node:v8: getHeapSnapshot y writeHeapSnapshot permiten inspeccionar el heap de Bun en Chrome DevTools
  • El servidor node:http2 es 2 veces más rápido que Node.js en Bun 1.2
  • express procesa solicitudes HTTP hasta 3 veces más rápido que Node.js gracias a mejoras en la compatibilidad de node:http y optimizaciones del servidor HTTP de Bun
  • También se añadió soporte para addons de C++ que usan la API C++ de V8
    • Node.js usa V8, mientras que Bun usa JavaScriptCore, por lo que la implementación es difícil
    • Bun implementa la API C++ pública de V8 sobre JavaScriptCore para que funcionen paquetes como cpu-features
    • Como el soporte de la API C++ de V8 es complejo, todavía puede faltar funcionalidad para la mayoría de los paquetes, y sigue mejorando el soporte para paquetes como node-canvas@v2 y node-sqlite3

API integrada de S3 Bun.s3

  • Bun 1.2 añade la API integrada Bun.s3 para manejar almacenamiento de objetos compatible con S3
    • Puede usarse con servicios que implementan la API de S3, como Amazon S3, Google Cloud Storage y Cloudflare R2
    • Maneja lectura, escritura y eliminación de archivos con una API compatible con el estándar Web Blob
  • s3.file() devuelve una referencia diferida a un archivo de S3, y puede usarse igual que la API File de Bun con métodos como text(), json(), arrayBuffer() y stream()
  • El cliente S3 de Bun está escrito en código nativo, no en JavaScript
    • Comparado con usar @aws-sdk/client-s3 en Node.js, descarga archivos de buckets S3 5 veces más rápido
  • Las funciones de escritura ofrecen write() y writer()
    • write() puede subir cadenas, Uint8Array, Blob, Response y más
    • writer() realiza carga multipart para archivos grandes
  • presign() genera una URL presignada que permite subir un archivo específico
    • Permite que los usuarios suban directamente a S3 sin exponer credenciales ni dar permisos innecesarios sobre el bucket
  • Al usarlo con Bun.serve(), new Response(s3.file(...)) redirige a una URL presignada en lugar de hacer que el servidor descargue y reenvíe el archivo de S3
    • Reduce memoria, tiempo y el costo de ancho de banda de que el servidor descargue el archivo
  • Las URL s3:// también pueden usarse con Bun.file() y fetch()
    • Con fetch("s3://...") es posible subir, descargar y eliminar
    • El S3Client predeterminado se configura con variables de entorno como AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY

Cliente Postgres integrado Bun.sql

  • Bun 1.2 añade Bun.sql, un cliente SQL integrado con soporte para Postgres
    • Bun ya ofrecía un cliente SQLite integrado, y en esta versión amplía el alcance del soporte para bases de datos SQL
    • También hay un pull request para añadir soporte de MySQL
  • Bun.sql ejecuta SQL con tagged-template literals
    • Permite pasar valores de JavaScript como parámetros SQL
    • Usa automáticamente escape de cadenas y prepared statements para prevenir SQL injection
  • Los resultados se devuelven como un arreglo de objetos con nombres de columnas como claves
  • Usa implementación en código nativo y varias optimizaciones
    • prepared statements automáticos
    • query pipelining
    • protocolo wire binario
    • connection pooling
    • caché de estructuras
  • La lectura de filas es hasta 50% más rápida que al usar clientes populares de Postgres en Node.js
  • La API está inspirada en postgres.js, y fue diseñada para facilitar la migración del código existente al cliente SQL integrado de Bun

Cambios en el gestor de paquetes

  • Bun 1.2 cambia el lockfile predeterminado de bun.lockb binario a bun.lock basado en texto
    • bun.lockb ayudó a que bun install fuera casi 30 veces más rápido que npm, pero era difícil ver su contenido en GitHub y complicaba revisar pull requests y resolver merge conflicts
    • A herramientas como Dependabot también les costaba leer el lockfile
  • bun.lock es un archivo JSONC
    • Soporta comentarios y trailing commas
    • Facilita revisar los diff en pull requests, y las trailing commas reducen la posibilidad de merge conflicts
  • Los proyectos nuevos generan bun.lock
    • Los proyectos existentes con bun.lockb seguirán soportando el lockfile binario sin migración automática
    • bun.lockb tendrá soporte a largo plazo, y bun add y bun update lo seguirán actualizando
    • Se puede migrar al nuevo lockfile de texto con bun install --save-text-lockfile
  • bun install sigue siendo 30% más rápido que Bun 1.1 incluso después del cambio al lockfile de texto
  • Se pueden usar comentarios y trailing commas en package.json
    • require() e import() también pueden leer ese package.json
    • Indican que no es una función ampliamente soportada en todo el ecosistema de JavaScript, así que recomiendan usarla “at your own risk”
  • Se agrega soporte para .npmrc
    • Lee .npmrc del root del proyecto y del directorio home
    • Puede usarse para registry, paquetes con scope y configuración de autenticación de registries privados
  • Nuevos comandos y opciones del gestor de paquetes
    • bun run --filter: ejecuta el mismo script al mismo tiempo en varios workspaces
    • bun outdated: revisa dependencias desactualizadas
    • bun publish: reemplazo de npm publish, con soporte para autenticación vía .npmrc, empaquetado de tarballs, OTP y manejo de edge cases de package.json
    • bun patch: guarda cambios hechos a dependencias como archivos .patch en patches/ y los aplica automáticamente durante bun install
    • --omit=dev|optional|peer: excluye dependencias dev, optional y peer de la instalación
    • Los certificados CA pueden configurarse desde bunfig.toml, flags de CLI y .npmrc
    • También hay soporte para bundleDependencies y para preservar la indentación de package.json con bun add

Mejoras en el test runner

  • bun test soporta el reporter JUnit XML
    • Con bun test --reporter=junit --reporter-outfile=junit.xml se pueden enviar resultados de pruebas a herramientas CI/CD como Jenkins, CircleCI y GitLab CI
    • También se puede configurar el reporte JUnit en bunfig.toml
  • La cobertura de código agrega un reporter LCOV
    • bun test --coverage --coverage-reporter=lcov genera coverage/lcov.info
    • --coverage-dir permite cambiar el directorio de salida
  • Soporta inline snapshots con expect().toMatchInlineSnapshot()
    • bun test -u o --update-snapshots actualiza los snapshots dentro del archivo de pruebas
    • También se pueden usar toThrowErrorMatchingSnapshot() y toThrowErrorMatchingInlineSnapshot()
  • test.only() ya funciona sin necesidad del flag --only
  • La API de expect() agrega matchers similares a los de Jest, Vitest y jest-extended
    • toContainValue(), toContainKey(), y la familia toHaveReturned()
    • Se puede pasar un mensaje de error personalizado como segundo argumento
  • jest.setTimeout() y setDefaultTimeout() permiten cambiar el timeout de prueba predeterminado del scope actual o del módulo

Bundler y funciones de build

  • Bun 1.2 soporta HTML import
    • Si se pasa un archivo HTML a la opción static de Bun.serve, agrupa automáticamente los <script> y <link> dentro del HTML y los expone como rutas estáticas
  • bun build --compile soporta compilación cruzada
    • Se pueden crear binarios de Windows o macOS desde Linux, y también a la inversa
    • En builds para Windows se pueden usar opciones para configurar íconos y ocultar la ventana de consola
  • bun build --bytecode genera un bytecode cache
    • Puede hacer que el tiempo de arranque de aplicaciones como eslint sea 2 veces más rápido
    • Los archivos .jsc contienen el bytecode cache del archivo .js correspondiente, y ambos archivos son necesarios para la ejecución
    • El bytecode cache puede ser 8 veces más grande que el código fuente, así que mejora el arranque a cambio de usar más espacio en disco
  • bun build --format=cjs permite especificar CommonJS como formato de salida
    • Antes solo se soportaba ESM
    • Facilita crear bibliotecas o aplicaciones dirigidas a versiones antiguas de Node.js
  • Se mejora la detección de CommonJS
    • Cuando un archivo es ambiguo, usa la directiva "use strict" del encabezado como última heurística de CommonJS
    • require.main === module se reescribe como import.meta.main para poder usarse junto con sentencias import
  • La API de plugins agrega el hook onBeforeParse()
    • Debe implementarse como un addon N-API, no en JavaScript
    • Permite manejar código fuente justo antes del parseo con casi cero overhead en lenguajes compilados como Rust, C/C++ y Zig
    • Es una API avanzada para autores de plugins y frameworks
  • También se amplían las opciones de build
    • --env="PUBLIC_*" inyecta variables de entorno en el bundle
    • Elimina llamadas a funciones con opciones como --drop=console
    • Agrega banner/footer
    • Bun.embeddedFiles() permite ver la lista de archivos incluidos en un ejecutable standalone
    • --ignore-dce-annotations ignora anotaciones incorrectas de dead-code elimination
    • --packages=external configura que las dependencias de paquetes no se incluyan en el bundle

Bundling de CSS

  • Bun 1.2 implementa un nuevo parser y bundler de CSS
    • Deriva del trabajo de LightningCSS, fue reescrito de Rust a Zig e integrado con el parser, bundler y runtime de JavaScript/TypeScript de Bun
  • Con bun build ./index.css se pueden combinar varios archivos CSS y referencias @import, url y @font-face en un solo archivo CSS
  • Se pueden importar archivos .css desde código JavaScript y TypeScript
    • Aplana en un solo archivo CSS por entrypoint el CSS importado y las reglas @import dentro del graph de módulos de JavaScript
  • La API Bun.build() también permite hacer bundling de CSS y JavaScript desde la misma API

Nuevas API del runtime de Bun

  • Bun.serve() admite rutas estáticas mediante la propiedad static
    • Se pasa la ruta como clave y el objeto Response como valor
    • Las rutas estáticas son hasta un 40% más rápidas que manejarlas directamente en el handler de fetch()
    • El body de la respuesta, los headers y el código de estado se almacenan en caché en memoria, por lo que no hay allocation de JavaScript ni garbage collection
    • Las rutas estáticas se pueden recargar con server.reload()
  • Bun.udpSocket() ofrece sockets UDP con la forma de la API de Bun
    • También es compatible con node:dgram, pero Bun.udpSocket() es una API moderna similar a Bun.listen()
    • Puede enviar varios datagramas UDP con una sola syscall y responder al backpressure del SO
  • Bun.file() admite delete(), unlink() y stat()
    • stat() devuelve metadatos con la misma forma que el objeto Stats de fs.stat() de Node.js
    • La misma API también se puede usar con archivos en S3
  • Bun.color() ofrece parsing, normalización y conversión de colores
    • Admite CSS, códigos de color ANSI, RGB, HSL y más
  • dns.prefetch() permite precargar registros DNS para calentar la caché DNS al inicio
  • Otras utilidades
    • Bun.inspect.table(): devuelve una cadena en formato de tabla, como console.table
    • Bun.randomUUIDv7(): genera UUID v7 monotónicos, adecuados para ordenamiento y bases de datos

Mejoras en el cliente SQLite

  • El cliente SQLite integrado de Bun puede mapear resultados de consultas a instancias de clases con query.as(Class)
    • Se pueden agregar getters, setters y métodos
    • Por rendimiento, no admite class constructor, default initializer ni private field
    • No gestiona relaciones ni genera SQL, así que no es un ORM
  • query.iterate() procesa las filas como iterator sin cargarlas todas en memoria de una vez
    • El propio objeto de consulta también se puede recorrer con un bucle for
  • Si se activa la opción strict, se pueden omitir los prefijos $, @ y : en los parámetros de la consulta
    • Si falta un parámetro, lanza un error
  • En el resultado de db.run() se puede ver cuántas filas cambiaron y el último row ID insertado
    • changes
    • lastInsertRowid
  • La opción safeIntegers devuelve enteros de 64 bits como BigInt en lugar de number truncado
    • Se puede configurar por base de datos o por consulta
  • Con la sintaxis using de JavaScript, statements y base de datos se pueden cerrar automáticamente al salir del scope

Compilar y ejecutar C desde JavaScript

  • Bun 1.2 agrega soporte experimental para compilar y ejecutar C desde JavaScript
    • Usa la API cc() de bun:ffi
    • Es una forma de usar bibliotecas del sistema en C desde JavaScript sin un build step separado
  • Bun incluye tinycc
    • A diferencia de gcc o clang, puede compilar código C simple en milisegundos
    • Permite compilar y ejecutar código C cuando haga falta
  • También se ofrece código C que usa N-API
    • Funciona solo con Bun, sin la etapa de build de node-gyp

Soporte para musl y Alpine Linux

  • Bun 1.2 agrega builds de Bun para distribuciones Linux que usan musl libc en lugar de glibc
    • Se puede usar en entornos como Alpine Linux
    • Admite Linux x64 y aarch64
  • En Docker se puede usar la imagen oven/bun:alpine
  • musl permite imágenes de contenedor más pequeñas, pero tiende a ser un poco más lento que la versión glibc de Bun
    • Salvo que haya una razón específica, se recomienda usar glibc

Funciones del lenguaje JavaScript

  • Se agregó soporte para import attributes
    • Permite importar indicando explícitamente JSON, texto, TOML, etc., como en import json from "./package.json" with { type: "json" }
    • También se puede usar en import() dinámico
  • Admite using y await using
    • Al salir del scope, se llama a [Symbol.dispose] o [Symbol.asyncDispose] para limpiar recursos automáticamente
    • Está soportado en varias API de Bun como Bun.spawn(), Bun.serve(), Bun.connect(), Bun.listen(), bun:sqlite y más
  • Nuevas API relacionadas con Promise
    • Promise.withResolvers(): crea promise, resolve y reject de una sola vez
    • Promise.try(): envuelve una función síncrona o asíncrona en una promise
  • API de errores y arreglos de bytes
    • Error.isError(): verifica con mayor precisión si algo es un Error, incluso con manipulación de prototype chain o en escenarios cross-realm de node:vm
    • Uint8Array.toBase64() / Uint8Array.fromBase64()
    • Uint8Array.toHex() / Uint8Array.fromHex()
  • Se agregaron iterator helpers
    • map, flatMap, filter, take, drop, reduce, toArray, forEach, find
  • Admite Float16Array
    • Los arreglos de punto flotante de 16 bits tienen menos precisión que los de 32 bits, pero son más eficientes en memoria

Nuevas Web API

  • Admite TextDecoderStream y TextEncoderStream
    • Son versiones en streaming de TextDecoder y TextEncoder
    • En Bun, TextEncoderStream es hasta 30 veces más rápido que en Node.js
  • Admite la opción stream de TextDecoder
    • Permite procesar chunks como parte de un stream más grande aunque no sean un code point UTF-8 completo
  • Se agregó el método bytes()
    • Devuelve datos de stream como Uint8Array en Response, Blob, Bun.file() y más
    • Reduce el proceso existente de usar arrayBuffer() y luego crear un Uint8Array
  • Admite upload en streaming con fetch()
    • Útil para subir archivos grandes o streams de datos cuyo content length no se conoce de antemano
  • Implementa console.group() y console.groupEnd()
  • Admite URL.createObjectURL()
    • Permite crear URL desde Blob y usarlas en fetch(), Worker e import()
    • Los scripts de Worker también pasan por el transpiler de Bun, por lo que pueden usar sintaxis de TypeScript
  • AbortSignal.any() combina varios AbortSignal para que, si uno se aborta, la señal padre también se aborte

Cambios de comportamiento y consideraciones de migración

  • Cambia el directorio de trabajo de bun run
    • Antes usaba el directorio de trabajo actual del shell
    • En Bun 1.2 usa como directorio de trabajo del script el directorio padre de package.json
    • Este cambio se hizo para alinearse con el comportamiento de npm y yarn
  • bun test ahora reporta como fallo los errores no capturados o las rejections entre pruebas
    • Antes, este tipo de errores podía no tratarse como fallo de prueba
  • server.stop() ahora devuelve Promise<void>
    • Puede esperar hasta que se cierren las conexiones HTTP en curso
  • Bun.build() ahora hace reject cuando falla, en lugar de poner el error en logs de un resultado resuelto
    • Si necesitas el comportamiento anterior, puedes configurar throw: false
  • bun -p pasa a ser un alias de bun --print para coincidir con Node.js
    • Antes era un alias de bun --port
  • El valor predeterminado de bun build --sourcemap cambia de inline source map a linked source map
    • Si necesitas el comportamiento anterior, usa --sourcemap=inline

Mejoras de rendimiento

  • Bun 1.2 incluye mejoras de rendimiento en varias rutas de ejecución
    • node:http2: 2 veces más rápido
    • Subidas a S3 mediante node:http: 5 veces más rápido
    • path.resolve(): 30 veces más rápido
    • Resolución DNS de fetch(): 2 veces más rápida
    • bun --hot: uso de memoria reducido a la mitad
    • fs.readdirSync() en macOS: leer directorios pequeños es 5% más rápido
    • String.at(): 44% más rápido
    • atob() con entradas de cadenas grandes: hasta 8 veces más rápido
    • Descompresión de datos gzip en fetch(): 30% más rápida
    • Buffer.from(string, "base64") con entradas grandes: de 6 a 30 veces más rápido
    • JSON.parse() con entradas de cadenas grandes: de 2 a 4 veces más rápido, y con entrada de objetos 6% más rápido
    • Rendimiento de algunas aplicaciones Bun.serve(): hasta 2 veces más
    • Error.captureStackTrace(): 9 veces más rápido
    • fs.readFile() con archivos pequeños: hasta 10% más rápido
    • console.log() con argumentos de cadena: 50% más rápido
  • En Windows se activa el JIT de JavaScriptCore
    • Antes, el JIT solo estaba disponible en macOS y Linux
    • En Windows, JavaScript ahora se ejecuta más rápido en general
    • Por ejemplo, Object.entries() es 20% más rápido y Array.map() 50% más rápido

Instalación y actualización

  • Nuevos comandos de instalación
    • curl -fsSL https://bun.sh/install | bash
    • powershell -c "irm bun.sh/install.ps1 | iex"
    • npm install -g bun
    • brew tap oven-sh/bun y luego brew install bun
    • docker pull oven/bun
  • Si Bun ya está instalado, se actualiza con bun upgrade

1 comentarios

 
GN⁺ 2025-01-25
Comentarios en Hacker News
  • No entiendo por qué meter bases de datos de terceros y librerías externas de S3 en el core o la biblioteca estándar
    Parece que estas cosas funcionan mejor como librerías opcionales, y este tipo de runtime debería elegir con muchísimo cuidado qué entra en la biblioteca estándar
    Ya desde ahora da la impresión de ser un proyecto tipo fregadero de cocina, donde le meten de todo

    • Creo que justamente esa postura es una de las razones por las que Bun llamó tanto la atención
      El enfoque de batteries included es popular en muchos lados y es una ruta válida de adopción
      Configurar TypeScript también es difícil, y lo mismo pasa con Webpack, S3, Postgres, Jest, etc., así que ese acceso simplificado a archivos y streams también resulta bastante interesante
      Supongo que solo queda ver cómo responden los proveedores de despliegue distribuido
    • Según entiendo, Bun recibió inversión de VC, así que en algún momento tendrá que generar dinero; por eso, si tuviera que adivinar, diría que quizá quieren convertirlo en un ejecutor todo en uno para crear dependencia del proveedor de una forma u otra
      Claro, también podría estar equivocado, pero meter este tipo de dependencias en el core o la biblioteca estándar realmente no tiene mucho sentido
    • Mucha gente ya le dijo eso mismo a Jared, el autor de Bun, pero la postura de Jared es que Bun debería traer todo lo necesario para un proyecto base
      Parece creer que, si lo mete en el core, puede optimizarlo mejor que una librería de terceros
      En lo personal me parece un enfoque equivocado y siento que Jared se está volviendo demasiado ambicioso, pero al final sigue siendo su proyecto de pasión
    • Estoy totalmente de acuerdo en que las librerías opcionales son mejores
      La forma en que lo expresa Bun es: “Bun busca ser un runtime de JavaScript cloud-first. Es decir, soporta todas las herramientas y servicios necesarios para ejecutar aplicaciones de producción en la nube”, pero esa frase no me da mucha confianza
      Esta decisión de diseño en particular se ve incluso peor que Node
    • Esto es para la oferta de servicio administrado de Bun
      El problema del software financiado por VC siempre ha sido que estas integraciones intentan ofrecer algo “propio” y, dicho de otra manera, buscan crear dependencia
  • Hasta ahora mi experiencia usando Bun ha sido muy buena
    Siempre me daba flojera configurar TypeScript/Jest/React/Webpack en proyectos nuevos por todos los cambios que rompían cosas aquí y allá, pero en Bun eso viene resuelto de fábrica y, para mi caso de uso, simplemente funciona sin dolor
    Sobre la integración de librerías de terceros como S3 o SQL no sabría qué decir, pero al menos parece que están concentrándose en lo más usado y en lo más pedido
    Está bueno que le haya devuelto algo de cordura al ecosistema de herramientas de Node.js

    • Me da curiosidad qué diferencia concreta te aporta Bun en ese stack frontend que mencionaste arriba
    • Yo he configurado bien proyectos de React/TypeScript también con Vite o Next.js
      Siento que se está subestimando cuánto han mejorado las otras herramientas con el tiempo
    • Bun es excelente
      Para mí es como un truco de productividad
      ChatGPT todavía no conoce muy bien Bun, así que ahí sí hay una pequeña pérdida de productividad, pero aun así Bun me gusta
  • Hay muchas cosas buenas, pero me preocupa si parte del comportamiento por defecto no se está yendo demasiado hacia comportamientos mágicos ocultos
    Si usas new Response(s3.file(...)), en vez de descargar el archivo de S3 al servidor y enviárselo al usuario, Bun redirige al usuario a la URL prefirmada del archivo en S3
    Como valor por defecto, me parece una decisión bastante sorprendente, y tampoco está nada claro cómo desactivar eso si no quieres exponer directamente tu bucket de S3

    • Respeto el espacio que Bun intenta abrirse, pero si sigues al creador en Twitter, da la impresión de que muchas decisiones están muy inclinadas a resultados de corto plazo y conveniencia, y que el impacto profundo de esos comportamientos mágicos se trata con demasiada ligereza
      Al principio este proyecto me entusiasmaba, pero viendo en redes esas decisiones de diseño públicas, dispersas y, en lo personal, a menudo cuestionables, no me da confianza su dirección a largo plazo
      Si se hubiera mantenido en v0.x, estaría bien, pero después de sacar la 1.0, el criterio para seguir ampliando la superficie de la API debería haber sido mucho más estricto
    • Solo hay que pasarle un stream a la respuesta
      Response(file.stream())
    • Entiendo por qué lo hicieron, pero no me gusta ese diseño
      Personalmente me suena a un comportamiento con efectos secundarios fuertes, y al leerlo parece que devuelve el contenido del archivo, no una URL
      Igual también me da curiosidad por qué molestaría tanto exponer el bucket
      Al ser una URL prefirmada, tampoco otorga un acceso amplio
      Preferiría una API explícita como Response((file(...).getPresignedURL())), o en todo caso una opción para activar ese comportamiento mediante una variable de entorno o una configuración de Bun
  • Con baterías incluidas sí marca una gran diferencia
    Esa es también la razón por la que gusta que APIs web como Fetch API, Service Workers, Web Components, ES6+ y WebRTC ahora sean nativas tanto en los runtimes de V8 como de WebKit
    Aun así, debe haber un límite
    Puede que S3 ya sea ir demasiado lejos, pero un driver SQL sí tiene sentido
    Aun así, el problema es hasta dónde incluir cosas
    Hay muchísimas bases de datos; ¿habría que incluir drivers para la mitad de ellas?
    Ya con ese nivel habría mucho código adicional y el ejecutable podría volverse más lento
    Además, meter APIs tan sensibles en Bun también puede hacer que se pasen por alto temas de seguridad
    Imaginen que por algún script o problema de rutas se ejecuta eval y Bun termina subiendo todo el archivo fuente a un S3 privado; en ese momento ya fue

    • Me pregunto si de verdad eso de que “si hay mucho código adicional el ejecutable se vuelve más lento” es así
      Dependiendo de cómo se cargue el código en runtime, podría ser algo casi despreciable
      Si la carga de código solo se activa cuando aparece una sentencia import, ¿no sería prácticamente nulo el sobrecosto de rendimiento?
      Incluso si está enlazado estáticamente, no me queda claro por qué el ejecutable se volvería perceptiblemente más lento solo por el hecho de que ese código exista
      Puede que el ejecutable que hay que cargar en memoria sea literalmente más grande, pero no parece algo que se sienta como lentitud
    • Antes hubo una discusión en HN sobre por qué los navegadores no dan soporte de primera clase a SQLite, y ese punto también podría aplicarse a Bun
      La cuestión central es quién asume la responsabilidad de mantener la librería y cómo se la modifica cuando SQLite cambia
      Si SQLite tiene un bug, ¿cómo lo arreglaría Bun?
      ¿En qué versiones habría que aplicar la corrección?
      Si un parche del runtime puede cambiar el comportamiento del código que corre encima, ¿qué pasa con los usuarios que ya dejaron workarounds hechos para el comportamiento anterior?
      Hasta cierto punto son problemas resolubles, pero también traen desventajas
      A partir de cierto momento deja de ser un runtime y pasa a ser una plataforma, con otras responsabilidades y problemas que eso implica
    • Creo que el argumento a favor de incluir S3 es que hay muchos servicios de almacenamiento de objetos que implementan una API compatible con S3
      No es realmente un estándar web, pero sí es algo que mucha gente usa de facto como si fuera un estándar
    • Se dice que “si hay mucho código adicional el ejecutable se vuelve más lento”, pero el artículo literalmente incluye benchmarks y muestra que Bun es dos veces más rápido que la solución más rápida en Node.js
  • Hace poco un cliente usa Bun en producción
    Escuché que la experiencia de desarrollo con Bun es absurdamente buena por su velocidad y simplicidad
    La experiencia de desarrollador juega un papel importante a largo plazo
    Si tu codebase o tus procesos son un desastre, terminas perdiendo gente buena a menos que pagues compensaciones de nivel FAANG

  • Todavía no he usado Bun, pero la lista de funciones es tan larga que me cuesta creer que todo sea sólido y esté libre de bugs
    Ojalá me equivoque, y tengo pensado probarlo en algún proyecto más adelante
    Desde una perspectiva de gestión de proyecto, me confunde un poco por qué están dedicando tiempo a soporte de S3 cuando todavía ni siquiera tienen compatibilidad 100% con Node.js
    Next.js es un ecosistema enorme, así que si pueden atraer clientes de Next.js podrían crecer mucho más que con soporte para S3

    • La compatibilidad al 100% es una buena victoria de marketing, pero la compatibilidad de cola larga quizá no haga mucha diferencia para el usuario promedio
      En el día a día, ¿cuánto de toda la superficie de API de Node.js se usa realmente?
      ¿Y cuánto se depende en la práctica de esos casos borde raros?
    • Hablar de “perspectiva de gestión de proyecto” asume que uno sabe qué es el proyecto
      La gente que trabaja en esto no son robots
      Hay tareas que toman tiempo solo para entenderlas, y mientras tanto se pueden hacer otras cosas
      Tampoco hay una sola persona haciendo todo
      Se dice “si atraen clientes de Next.js crecerán más”, pero ¿crecer hacia qué?
      Eso no genera dinero
      Este es un proyecto financiado por VC, y el objetivo no es regalar Bun para quedarse con todos los usuarios del mundo
    • Esa duda de que una lista tan larga de funciones sea sólida y esté libre de bugs se vuelve mayor sobre todo porque está escrito en Zig
      Zig tiene una seguridad de memoria muy baja
      Si se referencia una variable que ya no existe, en vez de dar un error de segmentación accede a memoria arbitraria no relacionada
      Dicen que incluso en modo debug y modo seguro ocurre así[0]
      ¿Tan difícil sería montar encima un sistema de vivacidad de memoria que marque los nombres de variables como muertos y bloquee el acceso si ya murieron?
      Al final todo se reduce a “no uses comportamiento indefinido”[1]
      Por eso no querría poner nada hecho en Zig en algo como un servidor web expuesto a internet
      [0] : https://news.ycombinator.com/item?id=41720995
      [1] : https://github.com/ziglang/zig/issues/16467#issuecomment-164...
    • No es tan sólido ni está libre de bugs
      Lo usé el año pasado y se me crasheaba todo el tiempo
    • Es bastante gracioso el cambio donde corrigieron el bug de bun add que no preservaba los espacios ni la indentación de package.json, y ahora dicen que conserva la indentación por extraña que sea
      No sé quién pidió eso ni por qué pensaron que valía la pena dedicarle código
  • Importar HTML está increíble y muy bueno
    Con soporte para importar HTML en Bun 1.2, dicen que se puede reemplazar toda la toolchain de frontend con una sola sentencia import
    Se puede empezar pasando una importación HTML a la opción static de Bun.serve

    import homepage from "./index.html";
    
    Bun.serve({  
      static: {  
        "/": homepage,  
      },
    
      async fetch(req) {  
        // ... api requests  
      },  
    });  
    
    • Me pregunto cómo haría esto para reemplazar, por ejemplo, a Vite
      ¿Permite hot module replacement, preprocesamiento de CSS y carga de plugins específicos de frameworks como el compilador SFC de Vue?
      Servir archivos estáticos no tiene nada de nuevo, así que siento que me estoy perdiendo algo
  • Pensaba que no había proyecto con un fracaso tan anunciado como una alternativa competidora de Node.js, pero menos mal que lo probé una vez
    Tuve que crear muchos scripts ejecutables independientes para procesar actualizaciones de archivos de texto y bases de datos SQLite, y pude usar TypeScript, bun:sqlite [1] y bun $ Shell [2] de inmediato, sin archivos de configuración ni gestión de dependencias npm locales
    Después también lo probé en proyectos nuevos de JS/TypeScript, donde aproveché el bundler integrado [3] y el soporte para pruebas [4], y la instalación de dependencias también termina al instante
    Que todo funcione rápido e inmediatamente realmente mejora la calidad de vida, y ahora Bun es mi primera opción para proyectos nuevos de 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

    • Yo igual
      Estaba más del lado de “todo esto va a llegar a npm el próximo año, ¿qué sentido tiene?”
      Al final probé Bun y de verdad me sorprendió
      Los pequeños elementos de la experiencia de desarrollo se van acumulando y hacen una gran diferencia
      En mis proyectos, Bun realmente se siente como la siguiente generación
  • Hace poco usé Bun por primera vez y la experiencia fue excelente
    Todos mis proyectos tienen Webpack o Vite configurado para usar TypeScript y, una vez configurado, casi siempre funciona perfecto, pero la configuración en sí es engorrosa y para scripts pequeños no vale la pena
    En cambio, Bun simplemente funcionó
    Para intentar ejecutar TS “directamente” desde la CLI, estuve de 10 a 30 minutos moviéndole a alguna herramienta tipo node-ts o algo así, lidiando con mensajes horribles como “no es un módulo”, “no se puede usar import/require”, “ESM/CJS”, y probé todas las soluciones típicas: cambiar el tipo de módulo en package.json, modificar tsconfig, cambiar la forma de usar import/require
    Intentaba correr un script de unas 200 líneas y, como último recurso, lo cambié a Bun; funcionó de maravilla

    • Las versiones recientes de Node.js ya soportan “simplemente ejecutar TS” en casos como este
      node --experimental-strip-types index.ts
      Si no tienes una versión reciente de Node, el paquete tsx me funcionó bien
      Me fue mejor que ts-node
      Eso sí, ambas opciones simplemente descartan la información de tipos, y Bun hace lo mismo
  • Me gusta la dirección que está tomando
    En especial, incluir soporte nativo para S3 y Postgres tiene mucho sentido como alternativa al estado actual de “armar tu framework por tu cuenta”
    En todos los frameworks web como Rails y Laravel esto es estándar, y el ecosistema de JS podría beneficiarse muchísimo de ello
    Creo que el siguiente paso son migraciones y gestión de esquemas, además de una mejor experiencia de pruebas por defecto que permita configurar bien factories