Bun vs NodeJS
Богдан, Surf Frontend DeveloperNodeJS — самый известный JavaScript runtime, созданный в 2009 году Райаном Далом с использованием движка V8, написанный на C++. Это не фреймворк и не библиотека, а именно среда выполнения JS.
Со временем она росла и расширялась, увеличивая свою сложность. И для разработки требовалась всё больше вычислительной мощности.
Пытаясь решить эту проблему, 8 сентября 2023 года выходит новый JS runtime, основанный на Zig — Bun. С той самой огромной пельмешкой на логотипе.
Но самое интересное, что Bun является не только новым JS runtime. Если, например, для установки каких-либо пакетов в твой проект нужно было использовать npm/yarn/pnpm, то в Bun пакетным менеджером является он сам, как и бандлером, и тест-раннером.
Сравним по порядку.

Установка
NodeJS
Чаще всего ставят через скачку установщика одной из рекомендуемых версий (для всех ОС):
- LTS (Long Time Support) — самая стабильная.
- Current, она же Latest — самая последняя.
Bun
Установить можно через:
- Консоль (для Linux/MacOS):
curl -fsSL https://bun.sh/install | bash
- NPM:
npm install -g bun
- Docker
- Другие способы из документации
Контроль версий
NodeJS
Имеется множество версий, новейшая на момент выхода поста — 21.2.0. Чтобы работать с проектами на разных версиях ноды, можно поставить Node Version Manager (nvm). С ним можно управлять, устанавливать и переключаться между любыми версиями. Есть специальная версия nvm для Windows.
Bun
Смена версий происходит чуть сложнее. Для установки Bun другой версии необходимо поставить его, указав конкретную версию:
curl -fsSL https://bun.sh/install | bash -s “bun-v1.0.0”
Есть аналоги nvm — bum, bvm, но их поддерживают только unix-подобные системы.
JavaScript Engine — перевод в машинный код и работа с ним
NodeJS
Использует V8 — движок Google для Chrome. Он приоритезирует быстрое выполнение, что может увеличить использование памяти.
Bun
Использует JavaScriptCore — движок работы JS в браузере Safari от Apple. JSC отдает приоритет ускоренному времени запуска и уменьшению использования памяти в ответ на небольшое замедление выполнения программы.
При запуске кода с обычным console.log(‘Hello World’) Bun обгоняет NodeJS с разницей х4.
Транспиляторы
NodeJS
Хоть это и мощная среда выполнения JS, в неё не встроена поддержка TypeScript-файлов. Чтобы поработать с TS, нужно поставить дополнительные зависимости для переноса TS-кода в JS, а затем его запустить.
Bun
Транспилятор для работы с JS, TS, JSX, TSX-файлами встроен прямо в среду выполнения. Он просто переводит файл в JavaScript без посторонних модулей, что увеличивает скорость работы.
Работа с модулями
NodeJS
В самом JS их много: UMD, AMD и другие. Самые популярные — CommonJS и ESM, но с ограничениями: например, нельзя в одном файле использовать одновременно require и import.
Bun
Из коробки поддерживает CommonJS и ESM без дополнительной конфигурации, а значит может сочетать в одном файле ‘import’ и ‘require’.
CommonJS — модульная система, созданная для сервера Node.js (использует ‘require’ и ‘module.exports')
ESM — использует операторы ‘import’ и ‘export’, обеспечивающие более статический и асинхронный подход с оптимизацией работы с браузерами.
WebAPI
Если вы писали когда-нибудь код на JS, то по-любому сталкивались с этим понятием. Благодаря ему мы можем использовать те же самый Fetch API, WebSocket API и другие.
WebAPI в браузере — это набор интерфейсов, предоставляемых браузером для взаимодействия веб-страниц с внешними сервисами и ресурсами. Если кратко, это инструменты, расширяющие возможности браузера с поддержкой запросов и сложных операций.
NodeJS
До 18-й версии без установки необходимых пакетов браузером нативно не поддерживались стандартные WebAPI, разработчики должны были ставить дополнительные пакеты для корректной работы.
Bun
Предлагает встроенную поддержку дефолтных WebAPI, реализованных уже внутри, то есть реализует эти веб-стандартные API-интерфейсы вместо внедрения новых API. Но самих WebAPI немного — список доступных есть в документации.
Hot Reloading
Hot Reloading (HR) — полезная фича, позволяющая работать с кодом и видеть изменения в реальном времени.
NodeJS
Можно использовать пакет nodemon, который позволяет реализовывать HR в веб-приложении. Но пакет может привести к сбоям, таким как отключение HTTP- и WebSocket-соединений.
Bun
Достаточно прописать флаг –hot при запуске файла.
В то же время не происходит полная перезагрузка процесса, как в NodeJS, а лишь перезапуск без завершения прошлого процесса. Значит, соединение будет установлено непрерывно как для HTTP, так и WebSocket-соединений.
Пакетный менеджер
NodeJS
Имеет несколько пакетных менеджеров: npm, yarn, pnpm. npm — официальный, устанавливается вместе с nodejs; yarn повышает скорость и производительность в сравнении с npm.
Bun
В отличие от NodeJS, есть встроенный пакетный менеджер, причём очень быстрый. Bun в 29 раз быстрее, чем npm и в 33 раза, чем yarn. Достигается это за счёт глобального кэша, который используется без дополнительных установок как в npm.
Bundler
Bundling — процесс получения файлов JS и объединение их в единый оптимизированный пакет.
NodeJS
Сборка происходит за счёт сторонних инструментов: Webpack, Parcel и других.
Bun
Имеет встроенный бандлер, не уступающий даже Webpack — на нём сборка проекта занимает в среднем 38 секунд, в то время как Bun нужно 0.17 секунд.
Достигается скорость за счёт макросов — во время сборки проекта bun извлекает нужную информацию, встраивая её в конечный файл. На macOS и Linux она проходит хорошо, но вот на Windows пока поддерживается только среда выполнения JavaScript — менеджер пакетов, средство запуска тестов и сборщик отключены до тех пор, пока они не станут более стабильными.
Тесты
Тестирование всегда было неотъемлемой частью мира разработки. Благодаря ему разработчик может просмотреть поведение как отдельных модулей, так и в целом веб-приложения по своему сценарию.
NodeJS
Есть множество тест раннеров для frontend-разработки, — Jest, Cypress, Playwrite — которые можно поставить в проект на NodeJS. Вот пример кода обычного модульного теста на Jest:
test(‘one plus one is two', () => {
expect(1 + 1).toBe(2);
});
Для запуска (в данном случае yarn):
yarn jest
Bun
Он, как волшебная коробочка, сочетает в себе бандлер, пакетный менеджер, JS runtime даже и тест раннер, который схож по синтаксису с Jest, совместим с ним и поддерживает TypeScript и JSX:
import { test, expect } from "bun:test";
test("1 + 1", () => {
expect(1 + 1).toBe(2);
});
Для запуска:
bun test
Самое интересное — если мы импортируем Jest отдельно и используем его в проекте с Bun, импорт библиотеки в коде всё равно будет направлен на bun test.
Следовательно, его можно использовать в проектах без долгого переписывания импортов и всего синтаксиса, но, к сожалению, там реализовано не всё (информация по возможным методам тут).
Что касается скорости выполнения — снова тут выигрывает bun. Тот же самый expect().toEqual() будет выполняться на нём в 100 раз быстрее по сравнению с Jest.
Большая цифра, верно? Достигается она за счёт реализации матчеров в быстром нативном коде. Bun способен выполнить практически любой скрипт, созданный исходно для Node.js. Следовательно, Jest и все его последующие обновления сразу готовы к использованию.
Подводим итоги
NodeJS — самый известный JS runtime, который сочетает в себе огромную экосистему, но время идёт и на данный момент на рынок выходит Bun.
Он недавно вышел, но уже на этапе первого релиза показывает себя во всей красе не только по производительности, но и по количеству внутреннего функционала.
Но тем не менее, на данный момент внедрение его в продакшен не рекомендуется. Например, на данном релизе (1.0.0) нет полной поддержки http/2, Node API, а также нельзя сконфигурировать бандлер, из-за чего могут возникнуть проблемы при компиляции.
В общем и целом, да, это круто, но пока что сыро, поэтому посмотрим, что же будет дальше :)