Bun vs NodeJS

Bun vs NodeJS

Богдан, Surf Frontend Developer

NodeJS — самый известный 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, а также нельзя сконфигурировать бандлер, из-за чего могут возникнуть проблемы при компиляции.

В общем и целом, да, это круто, но пока что сыро, поэтому посмотрим, что же будет дальше :)

Полезные статьи

NodeJS

Bun

Общее


Report Page