Bun — инструментарий для сборки и тестирования full-stack приложений на JavaScript и TypeScript. Bun 1.4 добавляет 1517 тестов из набора тестов Node.js — самый большой скачок совместимости с Node.js со времён версии 1.0. Также релиз закрывает более 2900 issue, снижает холостое потребление CPU в 5 раз, снижает потребление памяти до 35% и ускоряет запуск на Linux на 50%. В версию вошли Bun.Image, Bun.WebView, Bun.markdown, Bun.cron(), Bun.Terminal, bun run --parallel, bun test --parallel, bun audit fix, bun dedupe и bun prune. Кроме того, рантайм переписан с Zig на Rust.
Материал охватывает все изменения, вышедшие с версии Bun 1.3.0.
Для обновления:
bun upgrade
Совместимость с Node.js
Bun создаётся как drop-in замена для Node.js. В набор тестов, запускаемых на каждом коммите Bun, добавлено 1517 тестов из тестового набора самого Node.js.
Модули node:http, node:fs, node:cluster, node:timers, node:zlib, node:vm и node:stream проходят 97% собственных тестов Node; node:quic — 99%; node:events, node:trace_events и node:sqlite — 100%.
Bun пока не совместим с Node.js на 100%, но на практике значительная часть существующей JavaScript-экосистемы работает без изменений. Прогресс совместимости с тестовым набором Node.js можно отслеживать на отдельной странице проекта.
Playwright
Playwright теперь работает на Bun: можно управлять браузером через connectOverCDP(), запускать набор тестов командой playwright test с конфигом playwright.config.ts, открывать --ui и запускать Chromium на Windows.
Next.js 16
bun --bun next build работает с Next.js 16.3, Turbopack и React Compiler.
vitest
vitest запускается под Bun, включая --coverage, с пулами threads и forks.
OpenTelemetry
Инструментация http и fs из OpenTelemetry экспортирует spans, а пакеты shimmer и require-in-the-middle патчат забандленный код.
dd-trace
dd-trace трейсит запросы, а @datadog/pprof непрерывно профилирует; C++ API V8, на которые они опираются, реализованы.
Дополнительные улучшения совместимости с Node.js
С каждым релизом Bun приближается к полной совместимости с Node.js. Без изменений теперь работают:
- Nuxt:
nuxt devподключает HMR и Nuxt DevTools. - testcontainers и dockerode: работает
container.exec(). - https-proxy-agent и socks-proxy-agent:
http.request()туннелирует через них. - crawlee: обходит через
proxy-chain. - @grpc/grpc-js и ConnectRPC: работают серверы за Envoy и клиенты за AWS ALB.
- amqplib: подключается к RabbitMQ.
- @aws-sdk/client-s3: работает потоковая загрузка.
- TypeORM: запускается с настройками декораторов из
tsconfig.json. - nock: перехватывает запросы
httpиhttps. - Fastify
inject()и light-my-request: работают. - happy-dom: больше не ломает
console.log. - piscina: работает.
Новые API Node.js в Bun:
worker_threads: опцииresourceLimits,stdout,stderrиeval.- ws: события
'upgrade'и'unexpected-response'. socket.upgradeTLS({ isServer: true }): серверный STARTTLS.node:cluster: разделяет слушающие сокеты между воркерами.node:repl,node:trace_events,node:domain: реализованы.
Production
Bun 1.4 использует меньше памяти, меньше CPU и запускается быстрее.
До версии 1.4 Bun использовал два аллокатора памяти — libpas от JavaScriptCore и mimalloc. Теперь JavaScriptCore в Bun использует mimalloc (что улучшает возврат памяти системе), а сам mimalloc расширен возможностями частичной очистки страниц, отдельным потоком-сборщиком, освобождающим память во время простоя JavaScript, и улучшенным ленивым обнулением.
Потребление CPU
Для Claude Code — крупного долгоживущего приложения на Bun — потребление CPU в production снизилось вдвое: p99 упал с 24% до 10%, p50 — с 5,8% до 2,5%.
Для небольшого приложения «hello world» холостое потребление CPU снижается в 5 раз.
Этого удалось достичь за счёт оптимизации моментов, когда таймеры сборщика мусора запрашивают GC, перехода JavaScriptCore с обхода Strong-корней в виде связного списка на связный список сегментированных массивов, а также сокращения числа вызовов futex — вместе с упомянутыми изменениями в mimalloc.
Потребление памяти
Приложения с HTTP-серверами на Bun должны увидеть снижение потребления памяти на 13-48%.
Пиковая память под нагрузкой (1 000 000 запросов при 64 соединениях; 100 000 для Next.js и Vite):
| Сервер | Bun 1.4 | Bun 1.3 | Node.js 26 | Δ к Bun 1.3 |
|---|---|---|---|---|
| fastify | 120 MB | 233 MB | 156 MB | −48% |
| Express | 92 MB | 169 MB | 145 MB | −46% |
node:http | 81 MB | 135 MB | 107 MB | −40% |
| Elysia | 55 MB | 91 MB | n/a | −40% |
| Next.js | 285 MB | 397 MB | 342 MB | −28% |
Bun.serve | 36 MB | 45 MB | n/a | −20% |
| Vite dev server | 233 MB | 268 MB | 214 MB | −13% |
Ещё большее снижение показывает серверный рендеринг с Next.js. На типовом паттерне App Router, который в версии 1.3 неограниченно рос (React.cache + no-store fetch в динамическом роуте), Bun 1.4 стабилизируется на 238 МБ после 4000 страниц — против 410 МБ у Node.
Запуск
На Windows Bun запускается в 2,5 раза быстрее.
hello.js на Windows | Bun 1.4 | Bun 1.3.14 | Node.js 26 |
|---|---|---|---|
| Время запуска | 15,5 мс | 39,0 мс | 40,1 мс |
| Пиковая память | 16,8 MB | 46,5 MB | 32,5 MB |
На Linux Bun запускается в 2 раза быстрее и использует меньше половины памяти.
hello.js на Linux | Bun 1.4 | Bun 1.3 | Node.js 26 |
|---|---|---|---|
| Время запуска | 5,1 мс | 10,9 мс | 27,2 мс |
| Пиковая память | 14,6 MB | 33,0 MB | 44,5 MB |
Размер бинарника
На Linux и Windows бинарник Bun стал меньше до 17%.
| Bun 1.4 | Bun 1.3.14 | |
|---|---|---|
| Linux x64 | 77,0 MB | 88,5 MB |
| Linux arm64 | 76,8 MB | 87,6 MB |
| Windows x64 | 84,8 MB | 93,9 MB |
| Windows arm64 | 75,1 MB | 90,2 MB |
| macOS arm64 | 61,2 MB | 60,2 MB |
| macOS x64 | 66,6 MB | 66,0 MB |
Бинарники для macOS стали примерно на 1 МБ больше.
Observability
Привычные инструменты работают с Bun 1.4.
bun --cpu-profзаписывает.cpuprofile. Открывается в Chrome DevTools или VS Code.bun --heap-profзаписывает совместимый с V8.heapsnapshot. Открывается в Chrome DevTools.node:inspector:Sessionможет запускать и останавливать CPU-профиль во время работы приложения черезProfiler.startиProfiler.stop.- Datadog:
dd-traceтрейсит запросы, а@datadog/pprofнепрерывно профилирует CPU. - OpenTelemetry: пакеты
@opentelemetry/instrumentation-httpи@opentelemetry/instrumentation-fsиз npm работают сnode:httpиnode:fsв Bun. Пакетыshimmerиrequire-in-the-middle, от которых они зависят, могут патчить забандленный код. - Асинхронные стектрейсы: ошибка из
fs.promises,fetch(), S3, DNS или crypto указывает наawaitв коде приложения, а не на нативные фреймы.
Часть возможностей появилась впервые.
--cpu-prof-md
--cpu-prof-md записывает CPU-профиль в формате Markdown, что позволяет находить горячую функцию прямо из терминала: топ функций по self time, дерево вызовов и кто кого вызывает. Файл можно прочитать по SSH, прогнать через grep, вставить в баг-репорт или передать LLM.
bun --cpu-prof-md ./app.ts
--heap-prof-md
--heap-prof-md записывает heap-профиль в формате Markdown, что позволяет из терминала понять, что удерживает память: общий размер, типы, удерживающие больше всего, самые крупные объекты и цепочки, которые не дают им освободиться.
bun --heap-prof-md ./app.ts
bun build --metafile-md
bun build --metafile-md записывает анализ бандла в формате Markdown, показывая, почему бандл получился большим: самые крупные модули, что грузит каждая точка входа, и цепочку импортов, которая затянула каждый файл.
bun build ./src/index.ts --outdir ./dist --metafile-md=./dist/meta.md
process.on("memoryPressure")
Когда операционная система сообщает о нехватке памяти, Bun получает уведомление и эмитит событие "memoryPressure" на process. Это можно использовать, чтобы освободить память до того, как ОС убьёт процесс: очистить кэш, закрыть простаивающие соединения, остановить неактивные воркеры. Работает на macOS, Linux и Windows.
process.on("memoryPressure", (level) => {
cache.clear();
pool.drainIdle();
});
- macOS:
kqueueсEVFILT_MEMORYSTATUS— то же событие, которое libdispatch использует дляDISPATCH_SOURCE_TYPE_MEMORYPRESSURE.levelпринимает значение"warning"или"critical". - Linux: триггер PSI, записываемый в
/proc/pressure/memory(илиmemory.pressurecgroup), отслеживается черезepollпо событиюEPOLLPRI.level—"critical". - Windows:
CreateMemoryResourceNotification(LowMemoryResourceNotification), ожидание черезRegisterWaitForSingleObject.level—"critical".
Потоки (Streams) и тела запросов
ReadableStream, WritableStream и TransformStream теперь реализованы нативно. Они используют меньше памяти, работают быстрее и проходят 100% Web Platform Tests.
Четыре конвейера, каждый перемещает 64 МБ данными по 4 КБ чанками:
- Скачивание:
fetch()→DecompressionStream("gzip")→TextDecoderStream→for await - Загрузка:
fs.createReadStream()→CompressionStream("gzip")→ тело POST-запроса черезfetch() - Транскодирование:
fs.createReadStream()→TextDecoderStream→TextEncoderStream→fs.createWriteStream() - Подпроцесс: тело
fetch()→ stdin процессаcat, затем stdoutcat→for await
Пропускная способность:
| Конвейер | Bun 1.4 | Bun 1.3 | Node.js 26 | Deno 2.9 |
|---|---|---|---|---|
| Скачивание | 1519 MB/s | n/a | 204 MB/s | 530 MB/s |
| Загрузка | 179 MB/s | n/a | 78 MB/s | 137 MB/s |
| Транскодирование | 132 MB/s | 116 MB/s | 52 MB/s | 91 MB/s |
| Подпроцесс | 751 MB/s | 505 MB/s | 256 MB/s | 170 MB/s |
Пиковая память:
| Конвейер | Bun 1.4 | Bun 1.3 | Node.js 26.7 | Deno 2.9 |
|---|---|---|---|---|
| Скачивание | 57 MB | n/a | 86 MB | 64 MB |
| Загрузка | 60 MB | n/a | 84 MB | 61 MB |
| Транскодирование | 62 MB | 92 MB | 72 MB | 57 MB |
| Подпроцесс | 65 MB | 207 MB | 106 MB | 114 MB |
Все четыре рантайма запускают один и тот же скрипт. Файловые потоки используют Readable.toWeb() и Writable.toWeb() из node:stream. В Bun 1.3 отсутствуют CompressionStream и DecompressionStream, поэтому для него в этих строках стоит n/a.
Response.clone() и Request.clone() больше не копируют каждый чанк во вторую ветку — клон теперь разделяет чанки тела с оригиналом.
Потоковое тело в 64 МБ, вызов res.clone(), затем чтение обоих тел:
| Рантайм | Пиковая память | Время |
|---|---|---|
| Bun 1.4 | 220 MB | 96 мс |
| Bun 1.3 | 311 MB | 129 мс |
| Node.js 26 | 382 MB | 230 мс |
| Deno 2.9 | 297 MB | 134 мс |
Чтение только клона, без чтения оригинала:
| Рантайм | Пиковая память | Время |
|---|---|---|
| Bun 1.4 | 155 MB | 63 мс |
| Bun 1.3 | 243 MB | 98 мс |
| Node.js 26 | 318 MB | 162 мс |
| Deno 2.9 | 233 MB | 104 мс |
Два вызова arrayBuffer() дают 128 МБ пиковой памяти в первой таблице. В обоих случаях Bun 1.4 экономит одну полную копию тела.