Bun 1.x no dia a dia: o que mudou na prática para apps Node.js existentes

1. Introdução ao Bun 1.x: por que isso importa agora?

1.1. O que é Bun e como ele se diferencia do Node.js tradicional

Bun é um runtime JavaScript all-in-one criado por Jarred Sumner, escrito em Zig, que combina runtime, bundler, test runner e gerenciador de pacotes em uma única ferramenta. Diferente do Node.js, que depende de V8 e do ecossistema npm com múltiplas ferramentas separadas, Bun usa JavaScriptCore da Apple e implementa internamente o que o Node.js delega a bibliotecas externas.

1.2. Compatibilidade com Node.js

O Bun 1.x oferece compatibilidade com a maioria das APIs Node.js. Código que usa http, fs, path, crypto e process geralmente funciona sem alterações. Porém, módulos nativos (C++ addons) e pacotes que dependem de bindings específicos do Node.js podem apresentar problemas.

1.3. Cenário atual em 2025

Em 2025, Bun já é estável o suficiente para ambientes de desenvolvimento e produção em projetos com perfil adequado. A migração vale a pena quando o ganho em velocidade de startup, execução de testes e instalação de dependências supera os riscos de incompatibilidade.

2. Instalação e primeiros passos em projetos existentes

2.1. Substituindo node por bun

O comando básico para rodar um arquivo JavaScript com Bun:

# Node.js
node server.js

# Bun
bun server.js

Para scripts npm, use bun run:

# npm
npm run dev

# Bun
bun run dev

2.2. Gerenciamento de dependências

bun install é significativamente mais rápido que npm install:

# Comparação de velocidade (projeto com 500 dependências)
npm install   # ~30 segundos
bun install   # ~3 segundos

O Bun gera um lockfile próprio (bun.lockb), mas também respeita package-lock.json e yarn.lock.

2.3. Configuração mínima para rodar apps populares

Express:

// index.js
import express from 'express';
const app = express();

app.get('/', (req, res) => {
  res.send('Hello from Bun + Express!');
});

app.listen(3000, () => console.log('Server running'));

Execute com: bun run index.js

Next.js:

# No package.json, adicione:
"scripts": {
  "dev": "bun run next dev",
  "build": "bun run next build",
  "start": "bun run next start"
}

3. Performance no dia a dia: o que realmente acelera

3.1. Startup time e cold starts

Em APIs e CLIs, a diferença é notável:

# Teste de startup (aplicação Express simples)
node server.js   # ~180ms
bun server.js    # ~30ms

Para funções serverless e cold starts, Bun reduz drasticamente o tempo de inicialização.

3.2. Execução de scripts e tarefas

bun run é mais rápido que npm run porque não carrega o gerenciador de pacotes completo:

# Script de build
npm run build   # ~2.5s (incluindo carregamento do npm)
bun run build   # ~0.8s (apenas execução do script)

3.3. Test runner nativo

Substituindo Jest ou Vitest por bun test:

// test/soma.test.js
import { describe, expect, test } from 'bun:test';

describe('soma', () => {
  test('deve somar dois números', () => {
    expect(1 + 2).toBe(3);
  });
});
# Comparação de velocidade (100 testes unitários)
npx jest       # ~4s
bun test       # ~0.6s

4. APIs nativas do Bun que substituem módulos Node.js

4.1. Bun.file() e Bun.write()

Leitura e escrita simplificadas:

// Com Node.js fs/promises
import { readFile, writeFile } from 'fs/promises';
const data = await readFile('arquivo.txt', 'utf-8');
await writeFile('saida.txt', data.toUpperCase());

// Com Bun
const file = Bun.file('arquivo.txt');
const text = await file.text();
await Bun.write('saida.txt', text.toUpperCase());

4.2. Bun.serve() como alternativa a Express/Koa

Para APIs leves, Bun.serve() elimina dependências externas:

Bun.serve({
  port: 3000,
  fetch(request) {
    const url = new URL(request.url);
    if (url.pathname === '/api/hello') {
      return new Response(JSON.stringify({ message: 'Hello' }), {
        headers: { 'Content-Type': 'application/json' }
      });
    }
    return new Response('Not Found', { status: 404 });
  }
});

4.3. SQLite integrado

Sem necessidade de better-sqlite3 ou sql.js:

import { Database } from 'bun:sqlite';

const db = new Database('app.db');
db.run('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)');
db.run('INSERT INTO users (name) VALUES (?)', ['Alice']);
const users = db.query('SELECT * FROM users').all();
console.log(users);

5. Compatibilidade com ecossistema Node.js

5.1. Módulos nativos e C++ addons

Pacotes como bcrypt, sharp e node-canvas podem falhar. Workaround:

# Use versões puras em JavaScript
npm install bcryptjs  # substitui bcrypt (C++)
npm install jimp      # substitui sharp (C++)

5.2. Ferramentas populares

Relato prático de compatibilidade:

Ferramenta   | Funciona? | Observação
Prisma       | Sim       | Requer gerar cliente com --generator
Sequelize    | Sim       | Funciona com drivers SQLite e PostgreSQL
Puppeteer    | Parcial   | Pode precisar de flags específicas
Socket.IO    | Sim       | Testado com versão 4.x

5.3. Variáveis de ambiente e __dirname

Diferenças sutis:

// Node.js
console.log(__dirname);      // /home/projeto/src
console.log(process.cwd());  // /home/projeto

// Bun (__dirname não existe globalmente)
import.meta.dir;             // /home/projeto/src
process.cwd();               // /home/projeto

6. Migração gradual: estratégias para não quebrar tudo

6.1. Usando Bun como runtime alternativo

A flag --bun permite usar o runtime Bun com scripts npm:

# No package.json
"scripts": {
  "dev": "bun --bun next dev",
  "test": "bun --bun jest"
}

Isso executa o script com o runtime Bun, mas mantendo o ecossistema Node.

6.2. Adotando o bundler do Bun

Substitua Webpack ou Vite para builds de backend:

# Comando para bundle
bun build ./src/index.ts --outdir ./dist --target node

# Comparação de tempo de build
webpack build   # ~12s
bun build       # ~1.5s

6.3. Testes em paralelo no CI

Valide compatibilidade sem comprometer o pipeline:

# .github/workflows/ci.yml
jobs:
  test-node:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm install && npm test

  test-bun:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v1
      - run: bun install && bun test

7. Armadilhas comuns e como evitá-las

7.1. Problemas com node_modules

O Bun resolve dependências de forma diferente:

# Problema: hoisting diferente pode quebrar imports
# Solução: use bun install --yarn para comportamento mais próximo do Yarn

# Problema: peer dependencies não resolvidas automaticamente
# Solução: instale manualmente as peer dependencies
bun add react react-dom

7.2. Streams, buffers e eventos assíncronos

Diferenças de implementação:

// Node.js (comportamento esperado)
const stream = fs.createReadStream('arquivo.txt');
stream.on('data', (chunk) => console.log(chunk));

// Bun (pode precisar de adaptação)
const stream = Bun.file('arquivo.txt').stream();
for await (const chunk of stream) {
  console.log(chunk);
}

7.3. Debugging e logging

Ferramentas compatíveis:

Ferramenta      | Funciona? | Alternativa
node --inspect  | Sim       | bun --inspect
nodemon         | Sim       | bun --watch
pino            | Sim       | Funciona nativamente
winston         | Sim       | Testado com versão 3.x

8. Conclusão: Bun 1.x é para você agora?

8.1. Perfil de projetos que mais se beneficiam

  • APIs REST e GraphQL: ganho significativo em startup time e throughput
  • CLIs e scripts de automação: execução mais rápida e dependências reduzidas
  • Projetos com muitos testes: test runner nativo acelera o ciclo de desenvolvimento

8.2. O que ainda falta para Bun substituir Node.js completamente

  • Suporte completo a módulos C++ nativos
  • Ecossistema de ferramentas de debugging mais maduro
  • Adoção em plataformas serverless (AWS Lambda, Vercel, etc.)

8.3. Recomendações práticas

  1. Comece com um módulo pequeno e não crítico
  2. Meça o ganho real de performance no seu contexto
  3. Mantenha compatibilidade com Node.js até validar a migração
  4. Use bun --bun para testar gradualmente

Bun 1.x não é um substituto universal para Node.js, mas para muitos projetos, os ganhos em produtividade e performance justificam a adoção. Avalie seu caso específico, teste com métricas reais e decida com base em dados, não em hype.

Referências