Voltar para o Blog

Node.js 24 LTS: Todas as Novas Features do V8 13.6, npm 11 e Melhorias de Performance

Ola HaWkers, o Node.js 24 chegou oficialmente em maio de 2025 e esta programado para entrar em LTS (Long-Term Support) em outubro. Essa versao traz uma quantidade impressionante de novas features JavaScript, melhorias de performance e APIs modernizadas.

Se voce trabalha com JavaScript no backend, este guia vai te mostrar tudo que precisa saber sobre a nova versao.

Overview do Node.js 24

O Node.js 24 representa um salto significativo em capacidades.

Principais atualizacoes:

Componente Versao Anterior Node.js 24
V8 Engine 12.x 13.6
npm 10.x 11
Undici 6.x 7
libuv 1.48 1.50

Timeline de suporte:

  • Lancamento: Maio 2025
  • LTS Ativo: Outubro 2025 - Abril 2027
  • Manutencao: Abril 2027 - Abril 2028

Novas Features JavaScript

O V8 13.6 desbloqueia varias features ECMAScript modernas.

RegExp.escape

Finalmente temos uma forma nativa de escapar strings para uso em expressoes regulares.

// Antes - funcao manual (sujeita a bugs)
function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

// Agora - metodo nativo
const userInput = "Hello [World]! Price: $100";
const escaped = RegExp.escape(userInput);
// Resultado: "Hello \\[World\\]! Price: \\$100"

// Uso pratico em busca
function highlightText(text, searchTerm) {
  const safeSearchTerm = RegExp.escape(searchTerm);
  const regex = new RegExp(`(${safeSearchTerm})`, 'gi');
  return text.replace(regex, '<mark>$1</mark>');
}

const result = highlightText(
  "Preco: $50.00 (promocao)",
  "$50.00"
);
// "<mark>$50.00</mark>" corretamente destacado

Float16Array

Novo typed array para floats de 16 bits, ideal para ML e graficos.

// Float16Array - metade do tamanho de Float32Array
const float16Data = new Float16Array(4);
float16Data[0] = 1.5;
float16Data[1] = -2.25;
float16Data[2] = 3.14159; // Truncado para precisao de 16 bits
float16Data[3] = 0.0001;

console.log(float16Data.byteLength); // 8 bytes (vs 16 para Float32Array)

// Conversao entre tipos
const float32 = new Float32Array([1.5, 2.5, 3.5, 4.5]);
const float16 = new Float16Array(float32); // Conversao automatica

// Util para WebGL e Machine Learning
class NeuralNetworkLayer {
  constructor(inputSize, outputSize) {
    // Pesos em Float16 economizam memoria
    this.weights = new Float16Array(inputSize * outputSize);
    this.biases = new Float16Array(outputSize);
  }

  forward(input) {
    // Computacao com precisao reduzida mas suficiente
    const output = new Float16Array(this.biases.length);
    // ... implementacao
    return output;
  }
}

Error.isError

Verificacao nativa se um valor e realmente um objeto Error.

// Antes - verificacao manual (falha com objetos de outros realms)
function isErrorOld(value) {
  return value instanceof Error;
}

// Agora - metodo nativo (funciona entre realms)
console.log(Error.isError(new Error('test'))); // true
console.log(Error.isError(new TypeError('test'))); // true
console.log(Error.isError(new RangeError('test'))); // true
console.log(Error.isError({ message: 'fake error' })); // false
console.log(Error.isError(null)); // false

// Uso pratico em error handling
function handleResponse(result) {
  if (Error.isError(result)) {
    logger.error('Operation failed:', result.message);
    return { success: false, error: result.message };
  }
  return { success: true, data: result };
}

// Funciona com erros de iframes/workers
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const IframeError = iframe.contentWindow.Error;
const iframeError = new IframeError('from iframe');

console.log(iframeError instanceof Error); // false (diferentes realms)
console.log(Error.isError(iframeError)); // true (funciona!)

Atomics.pause

Nova primitiva para sincronizacao de baixo nivel em Workers.

// Atomics.pause - util para spin-waiting eficiente
const sharedBuffer = new SharedArrayBuffer(4);
const sharedArray = new Int32Array(sharedBuffer);

// Worker esperando por valor
function waitForValue(expected) {
  while (Atomics.load(sharedArray, 0) !== expected) {
    // Pause permite que a CPU otimize o spin-wait
    Atomics.pause();
  }
  return sharedArray[0];
}

// Main thread sinalizando
function signalWorker(value) {
  Atomics.store(sharedArray, 0, value);
  Atomics.notify(sharedArray, 0);
}

// Implementacao de spinlock
class SpinLock {
  constructor(buffer, index) {
    this.array = new Int32Array(buffer);
    this.index = index;
  }

  acquire() {
    while (Atomics.compareExchange(this.array, this.index, 0, 1) !== 0) {
      Atomics.pause(); // CPU hint para aguardar
    }
  }

  release() {
    Atomics.store(this.array, this.index, 0);
  }
}

WebAssembly Memory64

Suporte a memoria de 64 bits para WebAssembly.

// WebAssembly com memoria de 64 bits
const memory64 = new WebAssembly.Memory({
  initial: 1,
  maximum: 65536, // Ate 4TB de memoria
  index: 'i64', // Indexacao 64-bit
});

// Permite enderecar mais de 4GB de memoria
// Util para aplicacoes de big data e ML

// Exemplo de uso com modulo WASM
const wasmCode = await fetch('/module.wasm');
const wasmBuffer = await wasmCode.arrayBuffer();

const wasmModule = await WebAssembly.instantiate(wasmBuffer, {
  env: {
    memory: memory64,
  },
});

// Processar datasets maiores que 4GB diretamente em WASM
const exports = wasmModule.instance.exports;
const result = exports.processLargeDataset(dataPointer, dataSize);

AsyncLocalStorage Melhorado

O AsyncLocalStorage agora usa AsyncContextFrame por padrao.

import { AsyncLocalStorage } from 'node:async_hooks';

const requestContext = new AsyncLocalStorage();

// Middleware Express/Fastify
function contextMiddleware(req, res, next) {
  const context = {
    requestId: crypto.randomUUID(),
    userId: req.user?.id,
    startTime: Date.now(),
  };

  requestContext.run(context, () => {
    next();
  });
}

// Logger que automaticamente inclui contexto
class ContextLogger {
  log(message, data = {}) {
    const ctx = requestContext.getStore();
    console.log(JSON.stringify({
      timestamp: new Date().toISOString(),
      requestId: ctx?.requestId,
      userId: ctx?.userId,
      message,
      ...data,
    }));
  }

  // Novo: Performance melhorada com AsyncContextFrame
  async logAsync(message) {
    // Contexto preservado mesmo em operacoes async complexas
    await someAsyncOperation();
    this.log(message);
  }
}

// Uso em qualquer lugar do codigo
const logger = new ContextLogger();

async function processOrder(orderId) {
  logger.log('Processing order', { orderId });

  // Mesmo em callbacks aninhados, contexto e preservado
  await db.transaction(async (trx) => {
    logger.log('Starting transaction');
    await trx.insert('orders', { id: orderId });
    logger.log('Order inserted');
  });

  logger.log('Order processed');
}

Melhorias de performance:

Operacao Node.js 22 Node.js 24
getStore() ~150ns ~50ns
run() overhead ~500ns ~200ns
Nested contexts Linear Constante

URLPattern Global

A API URLPattern agora esta disponivel globalmente.

// Antes - necessario import
// import { URLPattern } from 'urlpattern-polyfill';

// Agora - disponivel globalmente
const pattern = new URLPattern({
  pathname: '/users/:userId/posts/:postId',
});

// Matching de URLs
const url1 = 'https://api.example.com/users/123/posts/456';
const match = pattern.exec(url1);

console.log(match.pathname.groups);
// { userId: '123', postId: '456' }

// Patterns mais complexos
const apiPattern = new URLPattern({
  protocol: 'https',
  hostname: '*.example.com',
  pathname: '/api/v:version/:resource{/:id}?',
});

const testUrls = [
  'https://api.example.com/api/v2/users',
  'https://api.example.com/api/v2/users/123',
  'https://cdn.example.com/api/v1/files/abc',
];

testUrls.forEach(url => {
  const result = apiPattern.exec(url);
  if (result) {
    console.log('Match:', {
      subdomain: result.hostname.groups[0],
      version: result.pathname.groups.version,
      resource: result.pathname.groups.resource,
      id: result.pathname.groups.id,
    });
  }
});

// Router simples usando URLPattern
class PatternRouter {
  constructor() {
    this.routes = [];
  }

  add(method, patternString, handler) {
    this.routes.push({
      method,
      pattern: new URLPattern({ pathname: patternString }),
      handler,
    });
  }

  match(method, url) {
    for (const route of this.routes) {
      if (route.method !== method) continue;
      const match = route.pattern.exec(url);
      if (match) {
        return { handler: route.handler, params: match.pathname.groups };
      }
    }
    return null;
  }
}

const router = new PatternRouter();
router.add('GET', '/users/:id', getUserHandler);
router.add('POST', '/users', createUserHandler);
router.add('GET', '/posts/:postId/comments/:commentId?', getCommentsHandler);

npm 11

O npm 11 traz melhorias significativas.

Performance de Instalacao

# Instalacao mais rapida com cache otimizado
npm install

# Benchmark comparativo (projeto medio ~500 deps)
# npm 10: 45 segundos
# npm 11: 28 segundos (-38%)

# Novo algoritmo de resolucao de dependencias
# Menos duplicacao, arvore mais flat

Novos Comandos e Flags

# Query melhorada de dependencias
npm query ":root > :has([name^=@types/])"
# Lista todas as dependencias de tipos diretas

# Audit com mais detalhes
npm audit --format=json --detail

# Pack com preview
npm pack --dry-run --json
# Mostra exatamente o que seria incluido

# Instalacao seletiva
npm install --omit=dev --omit=optional --omit=peer

# Verificacao de integridade melhorada
npm doctor --fix
# Corrige problemas automaticamente quando possivel

Workspaces Aprimorados

# Execucao paralela em workspaces
npm run build --workspaces --parallel

# Filtragem por workspace
npm run test --workspace=packages/core --workspace=packages/utils

# Publicacao coordenada
npm publish --workspaces --tag latest

# Dependencias entre workspaces
npm install @myorg/utils --workspace=packages/core

Test Runner Nativo Melhorado

O test runner do Node.js recebeu melhorias significativas.

import { describe, it, before, after, mock } from 'node:test';
import assert from 'node:assert';

describe('UserService', () => {
  let db;
  let service;

  before(async () => {
    db = await createTestDatabase();
    service = new UserService(db);
  });

  after(async () => {
    await db.close();
  });

  // Novo: Subtests nao precisam mais de await explicito
  it('should create user', async (t) => {
    const user = await service.create({
      name: 'Test User',
      email: 'test@example.com',
    });

    // Subtests gerenciados automaticamente
    t.test('should have valid id', () => {
      assert.ok(user.id);
      assert.match(user.id, /^[a-f0-9-]{36}$/);
    });

    t.test('should have timestamps', () => {
      assert.ok(user.createdAt instanceof Date);
      assert.ok(user.updatedAt instanceof Date);
    });
  });

  // Novo: Mocking melhorado
  it('should send welcome email', async (t) => {
    const sendEmail = t.mock.fn(async () => ({ sent: true }));

    // Mock de modulo
    t.mock.module('../email-service.js', {
      namedExports: { sendEmail },
    });

    await service.create({ name: 'Test', email: 'test@test.com' });

    assert.strictEqual(sendEmail.mock.calls.length, 1);
    assert.strictEqual(
      sendEmail.mock.calls[0].arguments[0],
      'test@test.com'
    );
  });

  // Novo: Snapshot testing
  it('should format user correctly', async (t) => {
    const user = await service.getById('user-123');
    t.assert.snapshot(user);
  });
});

Executando testes:

# Executar todos os testes
node --test

# Com coverage
node --test --experimental-test-coverage

# Watch mode
node --test --watch

# Filtrar por nome
node --test --test-name-pattern="UserService"

# Reporter personalizado
node --test --test-reporter=spec

Undici 7

O cliente HTTP padrao foi atualizado para Undici 7.

import { request, fetch, Agent, Pool } from 'undici';

// Fetch com mais controle
const response = await fetch('https://api.example.com/data', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ query: 'test' }),
  // Novo: Controle de timeout granular
  signal: AbortSignal.timeout(5000),
});

// Pool de conexoes otimizado
const pool = new Pool('https://api.example.com', {
  connections: 10,
  pipelining: 6,
  keepAliveTimeout: 30000,
  keepAliveMaxTimeout: 60000,
});

// Requests usando pool
const { statusCode, body } = await pool.request({
  path: '/users',
  method: 'GET',
});

const data = await body.json();

// Agent customizado para retry
const retryAgent = new Agent({
  connect: {
    timeout: 10000,
  },
  // Novo: Retry automatico
  retry: {
    maxRetries: 3,
    minTimeout: 100,
    maxTimeout: 1000,
  },
});

// Streaming melhorado
const streamResponse = await fetch('https://api.example.com/stream', {
  dispatcher: retryAgent,
});

for await (const chunk of streamResponse.body) {
  process.stdout.write(chunk);
}

Deprecacoes e Remocoes

Algumas APIs foram depreciadas ou removidas.

url.parse() Depreciado

// Depreciado
import { parse } from 'node:url';
const parsed = parse('https://example.com/path?query=1');

// Recomendado: WHATWG URL API
const url = new URL('https://example.com/path?query=1');

console.log(url.hostname); // 'example.com'
console.log(url.pathname); // '/path'
console.log(url.searchParams.get('query')); // '1'

// Migracao de codigo legado
// Antes
const oldUrl = parse('https://user:pass@example.com:8080/path?q=1#hash');
console.log(oldUrl.auth); // 'user:pass'

// Depois
const newUrl = new URL('https://user:pass@example.com:8080/path?q=1#hash');
console.log(newUrl.username); // 'user'
console.log(newUrl.password); // 'pass'

tls.createSecurePair Removido

// Removido: tls.createSecurePair()

// Use tls.TLSSocket diretamente
import tls from 'node:tls';
import net from 'node:net';

const socket = net.connect(443, 'example.com');
const tlsSocket = new tls.TLSSocket(socket, {
  // opcoes
});

Migrando do Node.js 22

Guia pratico para atualizacao.

Checklist de Migracao

# 1. Verificar versao atual das dependencias
npm outdated

# 2. Atualizar dependencias que podem ter problemas
npm update

# 3. Verificar uso de APIs depreciadas
npx depcheck

# 4. Testar com Node.js 24
nvm install 24
nvm use 24
npm test

# 5. Verificar compatibilidade de native modules
npm rebuild

# 6. Atualizar engines no package.json
{
  "engines": {
    "node": ">=24.0.0"
  }
}

Breaking Changes Importantes

Mudancas que podem afetar seu codigo:

  1. url.parse() agora emite warning de depreciacao
  2. tls.createSecurePair foi removido
  3. Algumas flags experimentais foram removidas
  4. --experimental-specifier-resolution removido (use import maps)

Conclusao

O Node.js 24 representa uma evolucao significativa da plataforma. Com o V8 13.6, ganhamos features JavaScript modernas como RegExp.escape e Float16Array. O npm 11 traz instalacoes mais rapidas e workspaces aprimorados. O test runner nativo esta cada vez mais completo.

Para quem esta em producao com Node.js 20 ou 22, a migracao para 24 LTS (quando disponivel em outubro) sera tranquila para a maioria dos projetos. As depreciacoes sao poucas e bem documentadas.

Se voce quer explorar mais sobre o ecossistema JavaScript moderno, confira nosso artigo sobre ECMAScript 2025 e Novas Features JavaScript.

Bora pra cima! 🦅

📚 Quer Dominar Node.js do Zero ao Avancado?

Este artigo mostrou as novidades do Node.js 24, mas para aproveitar todo o potencial da plataforma, voce precisa de fundamentos solidos.

Material de Estudo Completo

Se voce quer construir uma base solida em JavaScript para dominar Node.js:

Opcoes de investimento:

  • 1x de R$9,90 no cartao
  • ou R$9,90 a vista

👉 Conhecer o Guia JavaScript

💡 JavaScript solido = Node.js dominado

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário