1 pontos por GN⁺ 2025-01-25 | 1 comentários | Compartilhar no WhatsApp
  • O Bun 1.2 é um grande lançamento voltado a uma ferramenta de desenvolvimento full-stack em JavaScript/TypeScript, expandindo junto a compatibilidade com Node.js e o runtime, bundler, testes e gerenciador de pacotes
  • O reforço na verificação de compatibilidade passou a executar a suíte de testes do Node.js a cada mudança, e foi adicionado suporte a node:http2, node:dgram, node:cluster, node:zlib e node:v8
  • As novas APIs integradas Bun.s3 e Bun.sql trazem para dentro do runtime o acesso a armazenamento de objetos compatível com S3 e ao Postgres, reduzindo a dependência de clientes externos
  • O gerenciador de pacotes muda o lockfile padrão do binário bun.lockb para o bun.lock baseado em JSONC, além de adicionar .npmrc, bun publish, bun patch, bun outdated e bun run --filter
  • Como mudaram o diretório de trabalho do bun run, o tratamento de falha do Bun.build(), o valor de retorno de server.stop(), o bun -p e o padrão de sourcemap, projetos existentes precisam verificar o impacto da migração

Reforço da compatibilidade com Node.js

  • O Bun 1.2 mudou o processo de melhoria de compatibilidade para executar a suíte de testes do Node.js a cada alteração no Bun
    • Antes, os bugs eram corrigidos principalmente com base em issues no GitHub ou relatos de falha ao executar pacotes npm, mas esse método era mais próximo de um “jogo de acertar toupeiras”, dificultando refatorações maiores
    • Milhares de arquivos de teste do repositório do Node.js foram portados para o Bun, e esses testes são executados a cada commit para verificar a compatibilidade
  • Como os testes do Node.js às vezes verificam detalhes internos de implementação e mensagens de erro exatas, o Bun ajustou alguns deles trocando bindings internos por stubs próprios ou focando a validação em name e code
    • O Bun tenta manter as mensagens de erro do Node.js sempre que possível, mas em alguns casos fornece mensagens mais úteis desde que name e code sejam iguais
  • Novos módulos e recursos do Node.js com suporte
    • node:http2: suporte à criação de servidores HTTP/2, necessário também para servidores gRPC
    • node:dgram: suporte a bind/connect de sockets UDP
    • node:cluster: permite executar várias instâncias do Bun para distribuir trabalho entre vários núcleos de CPU
    • node:zlib: a implementação em JavaScript foi reescrita em código nativo e ficou 2 vezes mais rápida que no Bun 1.1
    • node:v8: com getHeapSnapshot e writeHeapSnapshot, é possível inspecionar o heap do Bun no Chrome DevTools
  • O servidor node:http2 é 2 vezes mais rápido que o Node.js no Bun 1.2
  • O express processa requisições HTTP em até 3 vezes mais rápido que o Node.js graças a melhorias de compatibilidade com node:http e otimizações no servidor HTTP do Bun
  • Também foi adicionado suporte a addons em C++ que usam a API C++ do V8
    • O Node.js usa V8, enquanto o Bun usa JavaScriptCore, então a implementação é complexa
    • O Bun implementa a API C++ pública do V8 sobre o JavaScriptCore para permitir o funcionamento de pacotes como cpu-features
    • Como o suporte à API C++ do V8 é complexo, ainda pode haver recursos ausentes na maioria dos pacotes, e o suporte a pacotes como node-canvas@v2 e node-sqlite3 continua sendo aprimorado

API S3 integrada Bun.s3

  • O Bun 1.2 adiciona a API integrada Bun.s3 para lidar com armazenamento de objetos compatível com S3
    • Pode ser usada com serviços que implementam a API S3, como Amazon S3, Google Cloud Storage e Cloudflare R2
    • Leitura, gravação e exclusão de arquivos são tratadas com uma API compatível com o padrão Web Blob
  • s3.file() retorna uma referência tardia a um arquivo no S3 e pode ser usado da mesma forma que a API File do Bun, com text(), json(), arrayBuffer(), stream() e afins
  • O cliente S3 do Bun é escrito em código nativo, não em JavaScript
    • Em comparação com o uso de @aws-sdk/client-s3 no Node.js, o download de arquivos de buckets S3 é 5 vezes mais rápido
  • Os recursos de escrita oferecem write() e writer()
    • write() permite fazer upload de strings, Uint8Array, Blob, Response e outros tipos
    • writer() realiza upload multipart para arquivos grandes
  • presign() gera uma presigned URL que permite o upload de um arquivo específico
    • Isso permite que usuários façam upload direto para o S3 sem expor credenciais nem conceder permissões desnecessárias ao bucket
  • Quando usado com Bun.serve(), new Response(s3.file(...)) redireciona para uma presigned URL em vez de o servidor baixar e reenviar o arquivo do S3
    • Isso reduz memória, tempo e o custo de largura de banda do servidor ao baixar o arquivo
  • URLs s3:// também podem ser usadas em Bun.file() e fetch()
    • Com fetch("s3://..."), é possível fazer upload, download e exclusão
    • O S3Client padrão é configurado por variáveis de ambiente como AWS_ACCESS_KEY_ID e AWS_SECRET_ACCESS_KEY

Cliente Postgres integrado Bun.sql

  • O Bun 1.2 adiciona o cliente SQL integrado Bun.sql com suporte a Postgres
    • O Bun já oferecia um cliente SQLite integrado, e nesta versão amplia o suporte a bancos de dados SQL
    • Também há um pull request para adicionar suporte a MySQL
  • Bun.sql executa SQL com tagged-template literal
    • Valores JavaScript podem ser passados como parâmetros SQL
    • O uso automático de escape de strings e prepared statements evita SQL injection
  • Os resultados são retornados como um array de objetos com nomes de colunas como chave
  • A implementação usa código nativo e várias otimizações
    • prepared statements automáticos
    • pipelining de consultas
    • protocolo wire binário
    • pool de conexões
    • cache de estrutura
  • A leitura de linhas é até 50% mais rápida do que ao usar clientes Postgres populares no Node.js
  • A API foi inspirada em postgres.js e projetada para facilitar a migração de código existente para o cliente SQL integrado do Bun

Mudanças no gerenciador de pacotes

  • O Bun 1.2 mudou o lockfile padrão do binário bun.lockb para o bun.lock, baseado em texto
    • O bun.lockb ajudava a tornar o bun install quase 30 vezes mais rápido que o npm, mas era difícil ver seu conteúdo no GitHub e complicado revisar pull requests e resolver conflitos de merge
    • Ferramentas como o Dependabot também tinham dificuldade para ler o lockfile
  • O bun.lock é um arquivo JSONC
    • Suporta comentários e trailing commas
    • Fica mais fácil revisar diffs em pull requests, e as trailing commas reduzem a chance de conflitos de merge
  • Novos projetos passam a gerar bun.lock
    • Projetos existentes com bun.lockb continuam com suporte ao lockfile binário sem migração automática
    • O bun.lockb terá suporte de longo prazo, e bun add e bun update continuarão atualizando-o
    • É possível migrar para o novo lockfile em texto com bun install --save-text-lockfile
  • O bun install ficou 30% mais rápido que o Bun 1.1 mesmo após a mudança para lockfile em texto
  • É possível usar comentários e trailing commas no package.json
    • require() e import() também conseguem ler esse tipo de package.json
    • Como isso não é amplamente suportado em todo o ecossistema JavaScript, a recomendação é usar “at your own risk”
  • Foi adicionado suporte a .npmrc
    • Lê o .npmrc da raiz do projeto e do diretório home
    • Pode ser usado para configurar registry, pacotes com escopo e autenticação de registries privados
  • Novos comandos e opções do gerenciador de pacotes
    • bun run --filter: executa o mesmo script ao mesmo tempo em vários workspaces
    • bun outdated: verifica dependências desatualizadas
    • bun publish: substitui o npm publish, com suporte a autenticação via .npmrc, empacotamento de tarball, OTP e tratamento de edge cases do package.json
    • bun patch: salva alterações em dependências como arquivos .patch em patches/ e as aplica automaticamente durante o bun install
    • --omit=dev|optional|peer: exclui dependências dev, optional e peer da instalação
    • Certificados CA podem ser configurados em bunfig.toml, por flags de CLI e em .npmrc
    • Também há suporte a bundleDependencies e preservação da indentação do package.json no bun add

Melhorias no test runner

  • bun test agora suporta o reporter JUnit XML
    • Com bun test --reporter=junit --reporter-outfile=junit.xml, é possível enviar resultados de teste para ferramentas de CI/CD como Jenkins, CircleCI e GitLab CI
    • Também é possível configurar relatórios JUnit no bunfig.toml
  • A cobertura de código ganhou um reporter LCOV
    • bun test --coverage --coverage-reporter=lcov gera coverage/lcov.info
    • O diretório de saída pode ser alterado com --coverage-dir
  • Há suporte a inline snapshot com expect().toMatchInlineSnapshot()
    • bun test -u ou --update-snapshots atualiza o snapshot dentro do próprio arquivo de teste
    • toThrowErrorMatchingSnapshot() e toThrowErrorMatchingInlineSnapshot() também podem ser usados
  • test.only() agora funciona mesmo sem a flag --only
  • A API expect() ganhou matchers como os do Jest, Vitest e jest-extended
    • Inclui toContainValue(), toContainKey(), e a família toHaveReturned()
    • É possível passar uma mensagem de erro personalizada como segundo argumento
  • Com jest.setTimeout() e setDefaultTimeout(), dá para mudar o timeout padrão dos testes no escopo atual ou no módulo

Bundler e recursos de build

  • O Bun 1.2 suporta import de HTML
    • Ao passar um arquivo HTML para a opção static do Bun.serve, ele faz o bundling automático de <script> e <link> dentro do HTML e os expõe como rotas estáticas
  • bun build --compile agora suporta compilação cruzada
    • É possível gerar binários para Windows ou macOS a partir do Linux, e também no sentido inverso
    • Em builds para Windows, dá para definir ícone e usar a opção de ocultar a janela de console
  • bun build --bytecode gera um cache de bytecode
    • Pode reduzir pela metade o tempo de inicialização de aplicações como eslint
    • Arquivos .jsc armazenam o cache de bytecode do respectivo arquivo .js, e ambos são necessários para execução
    • O cache de bytecode pode ser 8 vezes maior que o código-fonte, trocando espaço em disco por inicialização mais rápida
  • bun build --format=cjs permite definir o formato de saída CommonJS
    • Antes, só havia suporte a ESM
    • Isso facilita criar bibliotecas ou aplicações voltadas a versões mais antigas do Node.js
  • A detecção de CommonJS foi aprimorada
    • Quando um arquivo é ambíguo, a diretiva "use strict" no topo passa a ser usada como heurística final para CommonJS
    • require.main === module é reescrito como import.meta.main, permitindo uso junto com instruções import
  • A API de plugins ganhou o hook onBeforeParse()
    • Ele precisa ser implementado como addon N-API, não em JavaScript
    • Permite manipular código-fonte logo antes do parsing com quase nenhum overhead em linguagens compiladas como Rust, C/C++ e Zig
    • É uma API avançada voltada a autores de plugins e frameworks
  • As opções de build também foram expandidas
    • --env="PUBLIC_*": injeta variáveis de ambiente no bundle
    • Remove chamadas de função com opções como --drop=console
    • Adição de banner/footer
    • Bun.embeddedFiles(): verifica a lista de arquivos incluídos em um standalone executable
    • --ignore-dce-annotations: ignora anotações incorretas de dead-code elimination
    • --packages=external: define que dependências de pacote não devem ser incluídas no bundle

Bundling de CSS

  • O Bun 1.2 implementa um novo parser e bundler de CSS
    • Ele deriva do trabalho do LightningCSS, foi reescrito de Rust para Zig e integrado ao parser, bundler e runtime de JavaScript/TypeScript do Bun
  • Com bun build ./index.css, é possível combinar vários arquivos CSS e referências @import, url e @font-face em um único arquivo CSS
  • Arquivos .css podem ser importados em código JavaScript e TypeScript
    • O CSS importado no grafo de módulos JavaScript, junto com regras @import, é achatado em um único arquivo CSS por entrypoint
  • A API Bun.build() também permite fazer bundling de CSS e JavaScript na mesma API

Adições à API de runtime do Bun

  • Bun.serve() oferece suporte a rotas estáticas com a propriedade static
    • Passe o caminho como chave e o objeto Response como valor
    • Rotas estáticas são até 40% mais rápidas do que tratá-las diretamente no handler fetch()
    • O corpo da response, os headers e o código de status ficam em cache na memória, sem allocation de JavaScript nem garbage collection
    • É possível recarregar as rotas estáticas com server.reload()
  • Bun.udpSocket() fornece sockets UDP no estilo da API do Bun
    • node:dgram também é suportado, mas Bun.udpSocket() oferece uma API moderna semelhante ao já existente Bun.listen()
    • Pode enviar vários datagramas UDP com uma única syscall e lida com backpressure do sistema operacional
  • Bun.file() oferece suporte a delete(), unlink() e stat()
    • stat() retorna metadados no mesmo formato do objeto Stats de fs.stat() do Node.js
    • A mesma API também pode ser usada com arquivos no S3
  • Bun.color() oferece parsing, normalização e conversão de cores
    • Suporta CSS, códigos de cor ANSI, RGB, HSL e mais
  • dns.prefetch() pode buscar registros DNS antecipadamente para aquecer o cache DNS na inicialização
  • Outros utilitários
    • Bun.inspect.table(): retorna uma string em formato de tabela, como console.table
    • Bun.randomUUIDv7(): gera UUID v7 monotônico, adequado para ordenação e bancos de dados

Melhorias no cliente SQLite

  • O cliente SQLite embutido no Bun pode mapear resultados de consulta para instâncias de classe com query.as(Class)
    • É possível adicionar getter, setter e method
    • Por questões de desempenho, constructor de classe, inicializadores padrão e campos privados não são suportados
    • Não gerencia relacionamentos nem gera SQL, portanto não é um ORM
  • query.iterate() processa linhas como iterator sem carregar tudo na memória de uma vez
    • O próprio objeto de consulta também pode ser percorrido com um loop for
  • Ao ativar a opção strict, é possível omitir os prefixos $, @ e : nos parâmetros da consulta
    • Se algum parâmetro estiver faltando, um erro será lançado
  • No resultado de db.run(), é possível verificar o número de linhas alteradas e o ID da última linha inserida
    • changes
    • lastInsertRowid
  • A opção safeIntegers retorna inteiros de 64 bits como BigInt, em vez de number truncado
    • Pode ser configurada no nível do banco de dados ou da consulta
  • Com a sintaxe using do JavaScript, statements e o banco de dados podem ser fechados automaticamente ao sair do escopo

Compilar e executar C a partir do JavaScript

  • O Bun 1.2 adiciona suporte experimental para compilar e executar C a partir do JavaScript
    • Usa a API cc() de bun:ffi
    • É uma forma de usar bibliotecas de sistema em C diretamente do JavaScript, sem etapa de build separada
  • O Bun vem com tinycc embutido
    • Diferentemente de gcc ou clang, ele pode compilar código C simples em milissegundos
    • Assim, é possível compilar e executar código C quando necessário
  • Também há suporte a código C que usa N-API
    • Funciona apenas com Bun, sem etapa de build com node-gyp

Suporte a musl e Alpine Linux

  • O Bun 1.2 adiciona builds do Bun para distribuições Linux que usam musl libc em vez de glibc
    • Pode ser usado em ambientes como Alpine Linux
    • Suporta Linux x64 e aarch64
  • No Docker, é possível usar a imagem oven/bun:alpine
  • O musl permite imagens de contêiner menores, mas tende a ser um pouco mais lento que a versão glibc do Bun
    • A menos que haja um motivo específico, o uso de glibc é recomendado

Recursos da linguagem JavaScript

  • Foi adicionado suporte a import attributes
    • É possível importar explicitamente JSON, texto, TOML etc., como em import json from "./package.json" with { type: "json" }
    • Também pode ser usado em import() dinâmico
  • Há suporte a using e await using
    • Ao sair do escopo, [Symbol.dispose] ou [Symbol.asyncDispose] é chamado para limpar recursos automaticamente
    • Há suporte em várias APIs do Bun, como Bun.spawn(), Bun.serve(), Bun.connect(), Bun.listen(), bun:sqlite e outras
  • Novas APIs relacionadas a Promise
    • Promise.withResolvers(): cria promise, resolve e reject de uma vez
    • Promise.try(): encapsula uma função síncrona ou assíncrona em uma promise
  • APIs de erro e arrays de bytes
    • Error.isError(): verifica com mais precisão se algo é um Error, mesmo com manipulação da prototype chain ou cenários cross-realm em node:vm
    • Uint8Array.toBase64() / Uint8Array.fromBase64()
    • Uint8Array.toHex() / Uint8Array.fromHex()
  • Foram adicionados iterator helpers
    • map, flatMap, filter, take, drop, reduce, toArray, forEach, find
  • Há suporte a Float16Array
    • Arrays de ponto flutuante de 16 bits têm menos precisão que os de 32 bits, mas são mais eficientes em memória

Adições à Web API

  • Há suporte a TextDecoderStream e TextEncoderStream
    • São versões em streaming de TextDecoder e TextEncoder
    • No Bun, TextEncoderStream é até 30 vezes mais rápido que no Node.js
  • Há suporte à opção stream de TextDecoder
    • Mesmo que um chunk não seja um code point UTF-8 completo, ele pode ser tratado como parte de um stream maior
  • Foi adicionado o método bytes()
    • Em Response, Blob, Bun.file() e outros, ele retorna dados de stream como Uint8Array
    • Reduz a etapa anterior de chamar arrayBuffer() e depois criar um Uint8Array
  • Há suporte a upload com fetch() em streaming
    • Útil para enviar arquivos grandes ou streams de dados cujo content length não é conhecido antecipadamente
  • console.group() e console.groupEnd() foram implementados
  • Há suporte a URL.createObjectURL()
    • É possível criar uma URL a partir de Blob e usá-la em fetch(), Worker e import()
    • Scripts de Worker também passam pelo transpiler do Bun, então podem usar sintaxe TypeScript
  • AbortSignal.any() combina vários AbortSignal, de modo que, se um deles for abortado, o signal pai também será abortado

Mudanças de comportamento e cuidados na migração

  • O diretório de trabalho de bun run mudou
    • Antes, ele usava o diretório de trabalho atual do shell
    • No Bun 1.2, o diretório pai de package.json é usado como diretório de trabalho do script
    • Essa mudança foi feita para alinhar o comportamento com npm e yarn
  • bun test agora reporta como falha erros não capturados ou rejeições entre os testes
    • Antes, esses erros podiam não ser tratados como falha de teste
  • server.stop() agora retorna Promise<void>
    • Agora é possível esperar até que as conexões HTTP em andamento sejam fechadas
  • Bun.build() agora faz reject em caso de falha, em vez de colocar o erro em logs de um resultado resolvido
    • Se você precisar do comportamento anterior, pode definir throw: false
  • bun -p agora é um alias de bun --print, em linha com o Node.js
    • Antes, era um alias de bun --port
  • O valor padrão de bun build --sourcemap mudou de inline source map para linked source map
    • Se você precisar do comportamento anterior, use --sourcemap=inline

Melhorias de desempenho

  • O Bun 1.2 inclui melhorias de desempenho em vários caminhos de execução
    • node:http2: 2x mais rápido
    • Upload para S3 via node:http: 5x mais rápido
    • path.resolve(): 30x mais rápido
    • Resolução de DNS em fetch(): 2x mais rápida
    • bun --hot: uso de memória reduzido pela metade
    • fs.readdirSync() no macOS: leitura de diretórios pequenos 5% mais rápida
    • String.at(): 44% mais rápido
    • atob() com entrada de string grande: até 8x mais rápido
    • Descompressão de dados gzip em fetch(): 30% mais rápida
    • Buffer.from(string, "base64") com entradas grandes: de 6x a 30x mais rápido
    • JSON.parse() com entrada de string grande: de 2x a 4x mais rápido; com entrada de objeto: 6% mais rápido
    • Vazão de algumas aplicações Bun.serve(): aumento de até 2x
    • Error.captureStackTrace(): 9x mais rápido
    • fs.readFile() com arquivos pequenos: até 10% mais rápido
    • console.log() com argumento de string: 50% mais rápido
  • No Windows, o JIT do JavaScriptCore foi ativado
    • Antes, o JIT só estava disponível no macOS e no Linux
    • No Windows, o JavaScript agora roda mais rápido de forma geral
    • Por exemplo, Object.entries() ficou 20% mais rápido e Array.map() 50% mais rápido

Instalação e upgrade

  • Novos comandos de instalação
    • curl -fsSL https://bun.sh/install | bash
    • powershell -c "irm bun.sh/install.ps1 | iex"
    • npm install -g bun
    • brew tap oven-sh/bun seguido de brew install bun
    • docker pull oven/bun
  • Para instalações existentes do Bun, faça o upgrade com bun upgrade

1 comentários

 
GN⁺ 2025-01-25
Opiniões no Hacker News
  • Não entendo por que colocar bancos de dados de terceiros e bibliotecas externas de S3 no core/na biblioteca padrão
    Acho que isso seria melhor como bibliotecas opcionais, e runtimes desse tipo precisam escolher com muito cuidado o que entra na biblioteca padrão
    Já começa a passar a sensação de um projeto que coloca tudo, até a pia da cozinha

    • Acho que essa postura em si é um dos motivos pelos quais o Bun chamou atenção
      A abordagem baterias incluídas é popular em muitos lugares e é um caminho escolhido com frequência
      Configurar TypeScript também é difícil, e o mesmo vale para Webpack, S3, Postgres, Jest etc.; então uma abordagem simplificada para arquivos e streams também é bem interessante
      É esperar para ver como os provedores de distribuição distribuída vão se posicionar
    • Pelo que sei, o Bun recebeu investimento de VC, então em algum momento vai precisar ganhar dinheiro; por isso, especulando, talvez a ideia seja transformá-lo em um executor tudo-em-um para criar algum tipo de lock-in de fornecedor
      Claro, posso estar errado, mas colocar essas dependências no core/na biblioteca padrão realmente não faz muito sentido
    • Muita gente disse a mesma coisa ao Jared, autor do Bun, mas a visão dele é que o Bun deve vir com tudo que um projeto básico precisa
      Parece que ele acredita que, ao colocar no core, dá para otimizar melhor do que com bibliotecas de terceiros
      Pessoalmente acho uma abordagem errada e sinto que o Jared ficou ambicioso demais, mas no fim das contas é o projeto de paixão dele
    • Concordo totalmente que bibliotecas opcionais seriam melhores
      Nas palavras do pessoal do Bun, “o Bun pretende ser um runtime JavaScript cloud-first. Ou seja, dá suporte a todas as ferramentas e serviços necessários para rodar aplicações em produção na nuvem”, mas isso não me inspira muita confiança
      Essa escolha específica de design parece ainda pior que a do Node
    • Isso é para o serviço gerenciado do Bun
      O problema de software bancado por VC sempre foi que essas integrações tentam oferecer algo próprio; em outras palavras, tentam criar dependência
  • Minha experiência usando Bun até agora tem sido muito boa
    Ao configurar TypeScript/Jest/React/Webpack em projetos novos, eu sempre ficava receoso por causa de mudanças incompatíveis quebrando coisas aqui e ali; no Bun isso é resolvido internamente e, para o meu uso, simplesmente funciona sem dor
    Não sei bem o que dizer sobre integrar bibliotecas de terceiros como S3 e SQL, mas pelo menos parecem estar focando nas coisas mais usadas e mais pedidas
    Gosto de ele trazer a sanidade que fazia falta ao ecossistema de ferramentas do Node.js

    • Fico curioso para saber que diferença o Bun faz na stack de frontend mencionada acima
    • Projetos React/TypeScript já vinham sendo bem configurados com Vite ou Next.js
      Parece que você está subestimando o quanto as outras ferramentas também evoluíram nesse meio-tempo
    • Bun é excelente
      Para mim, é como um cheat code de produtividade
      Há uma pequena perda de produtividade porque o ChatGPT não conhece bem o Bun, mas ainda assim gosto do Bun
  • Há muita coisa boa, mas me preocupa que parte do comportamento padrão esteja indo demais na direção de comportamento mágico escondido
    Ao usar new Response(s3.file(...)), em vez de baixar o arquivo do S3 para o servidor e enviá-lo ao usuário, o Bun redireciona o usuário para uma URL pré-assinada do arquivo no S3
    Como padrão, é uma escolha bastante surpreendente, e também não está nada claro como desativar isso quando você não quer expor diretamente o bucket S3

    • Respeito o espaço que o Bun está tentando abrir, mas, acompanhando o criador no Twitter, as decisões parecem muito enviesadas para resultados de curto prazo e conveniência, enquanto as implicações profundas desse comportamento mágico são tratadas de forma leve
      No começo eu tinha expectativa por esse projeto, mas, vendo nas redes as decisões de design esporádicas e, para mim, muitas vezes ruins, não confio na direção de longo prazo
      Se tivesse continuado como v0.x, tudo bem; mas, ao lançar a 1.0, o critério para aumentar a superfície da API deveria ter ficado muito mais alto
    • Basta passar um stream na resposta
      Response(file.stream())
    • Entendo por que fizeram isso, mas não gosto desse design
      Pessoalmente, parece um comportamento com efeitos colaterais fortes, e, ao ler, parece que ele retorna o conteúdo do arquivo, não uma URL
      Ainda assim, também fico curioso sobre o que incomoda em expor o bucket
      Por ser uma URL pré-assinada, ela não concede permissões amplas de acesso
      Uma API explícita como Response((file(...).getPresignedURL())) seria melhor; ou então uma opção para ativar esse comportamento por variável de ambiente ou configuração do Bun teria sido mais adequada
  • Baterias inclusas fazem uma grande diferença
    É por isso também que gosto do fato de APIs Web como Fetch API, Service Workers, Web Components, ES6+ e WebRTC agora serem nativas tanto nos runtimes V8 quanto WebKit
    Só que precisa haver um limite
    S3 talvez seja ir longe demais, mas drivers SQL fazem sentido
    Ainda assim, a questão é até onde incluir
    Existem muitos bancos de dados; devemos incluir drivers para metade deles?
    Mesmo só nesse nível, já seria bastante código extra, o que poderia deixar o executável mais lento
    Além disso, colocar uma API tão sensível no Bun pode fazer com que a segurança passe batida
    Imagine algum script ou problema de path fazendo eval ser executado e o Bun subir todos os arquivos-fonte para um S3 privado; nesse momento, acabou

    • Fico curioso se “muito código extra deixa o executável mais lento” é mesmo verdade
      Dependendo de como o código é carregado em runtime, vi que isso pode ser algo praticamente desprezível
      Se o carregamento de código só for disparado quando uma instrução import aparecer, então não há, na prática, overhead de velocidade, não?
      Mesmo que esteja linkado estaticamente, não entendo muito bem por que o executável ficaria mais lento em um grau relevante só porque o código existe
      Haveria o fato de o executável a ser carregado na memória ser literalmente maior, mas não parece algo que causaria lentidão perceptível
    • Houve uma discussão antiga no HN sobre por que navegadores não dão suporte de primeira classe ao SQLite, e esse argumento também pode se aplicar ao Bun
      O ponto central é quem fica responsável por manter a biblioteca e como essa biblioteca deve mudar quando o SQLite muda
      Se houver um bug no SQLite, como ele será corrigido no Bun?
      Em quais versões a correção deve entrar?
      Um patch do runtime pode mudar o comportamento do código que roda sobre ele; como lidar com usuários que criaram workarounds para o comportamento antigo?
      Até certo ponto são problemas solucionáveis, mas também vêm com desvantagens
      A partir de certo momento, deixa de ser um runtime e passa a ser uma plataforma, com outras responsabilidades e problemas decorrentes
    • Acho que o argumento a favor de incluir S3 está no fato de haver muitos serviços de armazenamento de objetos que implementam a API compatível com S3
      Não é exatamente um padrão Web de verdade, mas é algo que muita gente trata como um padrão de fato
    • Dizem que “muito código extra deixa o executável mais lento”, mas o texto literalmente traz benchmarks e mostra que o Bun é duas vezes mais rápido que a solução Node.js mais rápida
  • Recentemente, um cliente passou a usar Bun em produção
    Ouvi dizer que, por causa da velocidade e da simplicidade, a experiência de desenvolvimento com Bun é absurdamente boa
    A experiência do desenvolvedor tem um papel grande no longo prazo
    Se a base de código ou os processos forem uma bagunça, você vai perder bons profissionais, a menos que pague remuneração no nível FAANG

  • Ainda não experimentei o Bun, mas a lista de recursos é tão longa que fico cético sobre todos eles serem robustos e livres de bugs
    Espero estar errado e pretendo testar em algum projeto futuro
    Do ponto de vista de gestão de projeto, fico um pouco confuso sobre por que gastar tempo com suporte a S3 quando ainda nem há 100% de compatibilidade com Node.js
    Next.js é um ecossistema muito grande; se conseguirem trazer clientes do Next.js, isso pode gerar um crescimento muito maior do que suporte a S3

    • 100% de compatibilidade é uma boa vitória de marketing, mas a compatibilidade da cauda longa pode não fazer tanta diferença para o usuário médio
      No dia a dia, quanto de toda a superfície da API do Node.js você realmente usa?
      E quanto você realmente depende daqueles edge cases estranhos dentro dela?
    • Falar em “ponto de vista de gestão de projeto” pressupõe que se sabe o que é o projeto
      As pessoas que trabalham nele também não são robôs
      Algumas coisas levam tempo para serem entendidas e, nesse meio-tempo, dá para trabalhar em outras
      Também não é uma pessoa só fazendo tudo
      “Trazer clientes do Next.js traz mais crescimento”, mas crescimento em direção a quê?
      Isso não gera dinheiro
      Este é um projeto apoiado por VC, e o objetivo não é oferecer o Bun de graça para conquistar todos os usuários do mundo
    • Desconfio que uma lista longa de recursos seja toda robusta e sem bugs, especialmente porque foi escrita em Zig
      Zig tem segurança de memória muito baixa
      Se você referencia uma variável que já não está mais viva, em vez de uma falha de segmentação, ele acessa uma memória arbitrária não relacionada
      Dizem que isso acontece mesmo nos modos debug e seguro[0]
      Será tão difícil colocar por cima um sistema de tempo de vida de memória que marque nomes de variáveis como mortos e impeça o acesso quando estiverem mortos?
      No fim, vira “não use comportamento indefinido”[1]
      Por isso, eu não colocaria nada feito em Zig em algo como um servidor Web exposto à internet
      [0] : https://news.ycombinator.com/item?id=41720995
      [1] : https://github.com/ziglang/zig/issues/16467#issuecomment-164...
    • Não é muito robusto nem livre de bugs
      Usei no ano passado e ele ficava crashando
    • É bem engraçado o item dizendo que corrigiram um bug em que bun add não preservava espaços e indentação do package.json, e que agora preserva até a indentação mais estranha
      Não sei quem pediu isso nem por que acharam que valia a pena escrever código para isso
  • Importação de HTML é incrível e muito legal
    Com o suporte à importação de HTML no Bun 1.2, dizem que é possível substituir toda a toolchain de front-end por uma única instrução import
    Dá para começar passando a importação de HTML para a opção static do Bun.serve

    import homepage from "./index.html";
    
    Bun.serve({  
      static: {  
        "/": homepage,  
      },
    
      async fetch(req) {  
        // ... api requests  
      },  
    });  
    
    • Fico curioso sobre como isso permitiria substituir, por exemplo, o Vite
      É possível fazer hot module replacement, pré-processamento de CSS e carregamento de plugins específicos de frameworks, como o compilador de SFC do Vue?
      Servir arquivos estáticos não é exatamente novidade, então acho que estou deixando passar alguma coisa
  • Eu achava que não havia projeto mais fadado ao fracasso do que uma alternativa concorrente ao Node.js, mas foi bom ter experimentado
    Eu precisava criar muitos scripts independentes para lidar com atualizações de arquivos de texto e bancos SQLite, e pude usar TypeScript, bun:sqlite [1] e bun $ Shell [2] diretamente, sem arquivo de configuração nem gerenciamento de dependências npm locais
    Depois usei em novos projetos JS/TypeScript, e o bundler embutido [3] e o suporte a testes [4] também foram úteis, além de a instalação de dependências terminar instantaneamente
    Tudo funcionar rápido e de imediato é uma melhora real na qualidade de vida, e agora o Bun virou minha primeira opção para novos projetos 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

    • Eu também
      Eu era do tipo: “qual é o sentido, se essas coisas todas vão aparecer no npm no ano que vem?”
      Acabei testando o Bun e fiquei realmente surpreso
      Quando pequenos elementos da experiência do desenvolvedor se acumulam, a diferença é grande
      Nos meus projetos, o Bun realmente parece a próxima geração
  • Usei Bun pela primeira vez há pouco tempo e a experiência foi excelente
    Todos os meus projetos têm Webpack ou Vite configurado para usar TypeScript e, depois de configurados, funcionam quase perfeitamente, mas a configuração em si é trabalhosa e não vale a pena para scripts pequenos
    Já o Bun funcionou de cara
    Para tentar executar TS “diretamente” na CLI, fiquei mexendo por 10 a 30 minutos com alguma ferramenta chamada node-ts ou algo assim, encarando mensagens horríveis como “não é um módulo”, “não é possível usar import/require” e “ESM/CJS”, e tentei todas as correções comuns: alterar o tipo de módulo no package.json, mudar o tsconfig e trocar a forma de import/require
    Eu estava tentando executar um script de cerca de 200 linhas e, como último recurso, mudei para Bun; funcionou muito bem

    • O Node.js mais recente agora também suporta “simplesmente executar TS” nesses casos
      node --experimental-strip-types index.ts
      Se não for o Node mais recente, o pacote tsx funcionou bem para mim
      Foi melhor que ts-node
      Mas ambas as opções simplesmente descartam as informações de tipo, e o Bun também faz o mesmo
  • Gosto da direção
    Especialmente incluir suporte nativo a S3 e Postgres faz muito sentido, porque pode existir como alternativa ao estado atual de “montar seu próprio framework”
    Em todos os frameworks web como Rails e Laravel, isso é padrão, e o ecossistema JS também pode se beneficiar bastante disso
    Vejo o próximo passo como uma experiência básica de testes melhor, que faça bem migrações e gerenciamento de schema, além da configuração de factories