Bun или Node.js: что выбрать для проекта — решает не общий спор о скорости, а ограничения конкретного проекта. Для действующего сервиса на Node.js 22 LTS с нативным аддоном и хостингом без поддержки Bun ответ — остаться на Node.js. Для нового HTTP JSON сервиса на стандартных node:http и node:fs Bun подходит, если цель — единый инструментарий, а Node.js остаётся допустимым после той же приёмки.
Матрица по 11 критериям для проектов A и B
Ниже — заполненная матрица для двух условных проектов. Проект A: Node.js 22 LTS, Express, нативный аддон (модуль с node-gyp), хостинг без поддержки Bun, деплой через Docker-образ node:22. Проект B: новый HTTP JSON сервис, только стандартные node:http и node:fs, без нативных зависимостей, деплой на платформе с поддержкой Bun. Последний столбец фиксирует, откуда берётся утверждение: из документации или из локальной проверки.
| Критерий | Проект A | Проект B | Источник проверки |
|---|---|---|---|
| Движок | V8 (Node.js) | JavaScriptCore (Bun) | Документация обоих рантаймов |
| TypeScript | tsc в принятой сборке | запуск .ts средствами Bun, проверка типов отдельным шагом | Документация Bun |
| Пакетный менеджер | npm + package-lock.json | bun install + bun.lock | Документация Bun |
| Зависимости | Express установлен выбранным менеджером | для стандартных node:-модулей node_modules не требуется | Локальная проверка |
| Совместимость Node API | нативный рантайм | сверить конкретные node:-модули по справочнику | Справочник совместимости Bun |
| Нативные аддоны | критично, требуют проверки под Bun | не используются | Локальная сборка |
| Тесты | node:test | bun test (Jest-совместимый) | Документация Bun |
| Бандлинг | esbuild или tsup | bun build | Документация Bun |
| Single-file executable | SEA, больше шагов | bun build —compile | Документация Bun |
| Развёртывание | Docker node:22 | платформа с bunVersion | Документация Vercel |
| Миграция | не мигрировать без проверки аддонов | стартовать на Bun | Решение по итогам проверок |
Официальная документация Node.js описывает рантайм как среду на движке V8 с асинхронными примитивами ввода-вывода в стандартной библиотеке (nodejs.org). Документация Bun называет свой рантайм заменой Node.js на движке JavaScriptCore, написанным на Rust, и объединяет в одном исполняемом файле рантайм, пакетный менеджер, тест-раннер и бандлер (bun.com). Эти строки матрицы опираются на документацию.
Проект A: нативный аддон требует проверки под Bun
Для проекта A решающим оказывается нативный аддон. Документация Bun заявляет стремление к полной совместимости с встроенными глобалами и модулями Node.js и прямо называет эту работу продолжающейся (bun.com). Сборка нативного модуля через node-gyp опирается на заголовки и внутренние механизмы Node.js, поэтому статус такого модуля под Bun проверяется на месте.
Порядок проверки до любого решения о миграции:
- Соберите нативный аддон под Bun в отдельной ветке и зафиксируйте, проходит ли сборка.
- Если сборка проходит, запустите тесты проекта A под Bun и сравните поведение с прогоном на Node.js.
- Проверьте, поддерживает ли ваш хостинг Bun. В принятом примере хостинг проекта A поддержку Bun не предоставляет, и деплой идёт через Docker-образ node:22.
- Зафиксируйте результат проверки в матрице рядом со строкой «Нативные аддоны».
Пока сборка аддона под Bun не проверена, миграция проекта A остаётся нерешённой задачей. Ограничение хостинга в этом примере уже само по себе удерживает проект на Node.js: платформа без поддержки Bun не запустит сервис на этом рантайме. Документация Vercel показывает, как устроена поддержка на стороне платформы: рантайм Bun доступен в статусе Beta, версия задаётся свойством bunVersion в vercel.json, и допустимы значения «1.4.x» и «1.x» (vercel.com). Значение «1.4.x» выбирает переписанную версию Bun с несколькими ломающими изменениями, а «1.x» — предыдущую актуальную версию. Эти значения относятся к платформе Vercel и не описывают ваш хостинг.
Проект B: сверка node:-модулей со справочником
Проект B использует только стандартные node:http и node:fs, поэтому первый шаг — сверить именно эти модули со справочником совместимости Bun. Справочник отражает актуальную версию совместимости с Node.js v26 и помечает модули статусами: node:fs отмечен как полностью реализованный, и в документации указано, что 98% тестового набора Node.js проходит; node:http тоже отмечен как полностью реализованный, при этом http.Server не расширяет net.Server, а часть опций listen() игнорируется (bun.com).
Практический порядок сверки:
- Выпишите все node:-модули, которые импортирует проект B.
- Найдите каждый в справочнике совместимости и отметьте статус: полная реализация, частичная или отсутствие.
- Отдельно выпишите известные отличия по каждому модулю — они перечислены в справочнике рядом со статусом.
- Отметьте расхождения в матрице и решите, затрагивают ли они ваш код.
Для стандартных node:-модулей node_modules не требуется; каталог появится при установке внешних пакетов. Пакетный менеджер Bun создаёт bun.lock, и на платформах с поддержкой Bun это ожидаемый файл блокировки. Документация Vercel уточняет, что для пресета Bun нужен bun.lock и точка входа server в корне проекта или в каталоге src, а минимальный проект содержит package.json, bun.lock, server.ts и конфигурацию vercel.json (vercel.com). Эти детали относятся к деплою на Vercel; на другой платформе порядок задаётся её документацией.
Тесты проекта B через bun test
Тест-раннер Bun описан в документации как Jest-совместимый и ориентированный на TypeScript, с поддержкой снапшотов, DOM и режима наблюдения (bun.com). Для проекта B это означает, что существующие тесты можно прогнать через bun test и отметить расхождения.
Порядок прогона:
- Установите зависимости проекта B и убедитесь, что bun.lock создан.
- Запустите тесты через bun test и сохраните вывод.
- Сравните результат с прогоном на Node.js: отметьте упавшие тесты и различия в выводе.
- Для каждого расхождения проверьте, связано ли оно с тест-раннером или с поведением самого рантайма.
- Зафиксируйте расхождения в матрице рядом со строкой «Тесты».
Отдельного внимания требует модуль node:test. В справочнике совместимости он отмечен как частично реализованный: в процессе под bun test работают тесты, наборы, подтесты, хуки, t.plan(), t.assert и моки, а run() требует явного списка файлов и запускает каждый файл в дочернем процессе bun test; часть опций, включая globPatterns, watch, coverage и shard, возвращает ERR_NOT_IMPLEMENTED (bun.com). Если проект B опирается на node:test, этот статус влияет на план прогона. Для проектов на Jest-совместимом API переход на bun test проходит по документированному пути.
Проверка типов остаётся отдельным шагом. Запуск .ts средствами Bun и проверка типов — разные операции: документация Bun перечисляет bun check как отдельный инструмент проверки TypeScript-проекта (bun.com). В принятой сборке проекта A используется tsc, и этот выбор сохраняется независимо от рантайма.
Документированные возможности и локальные проверки
Разделение двух категорий утверждений — основа решения. Документированные возможности описывают рантайм в целом: движок, состав инструментов, статус модулей, допустимые значения конфигурации платформы. Локальные проверки описывают ваш код: собирается ли конкретный нативный аддон, проходят ли ваши тесты, ведёт ли себя ваш HTTP-сервис так же, как раньше.
| Утверждение | Категория | Как проверяется |
|---|---|---|
| Bun объединяет рантайм, менеджер, тест-раннер и бандлер | Документированное | Документация Bun |
| node:fs и node:http отмечены как полностью реализованные | Документированное | Справочник совместимости |
| node:test реализован частично | Документированное | Справочник совместимости |
| Нативный аддон проекта A собирается под Bun | Локальное | Сборка в отдельной ветке |
| Тесты проекта B проходят через bun test | Локальное | Прогон и сравнение с Node.js |
| Хостинг проекта A запускает Bun | Локальное | Проверка возможностей хостинга |
Документация Vercel приводит условия выбора: Bun подходит для новых нагрузок с быстрым единым инструментарием и встроенной поддержкой TypeScript и JSX, а Node.js стоит рассмотреть, когда он уже установлен и работает, когда нужны автоматические source maps для отладки или метрики запросов на node:http и node:https (vercel.com). Там же указано, что производительность зависит от нагрузки и в части операций Node.js может оказаться быстрее. Эти формулировки описывают платформу Vercel и служат ориентиром.
Решение по двум проектам
Для проекта A решение — остаться на Node.js. Причина в явно заданном ограничении хостинга и в том, что нативный аддон требует проверки под Bun до любого решения о миграции. Если хостинг изменится или сборка аддона под Bun пройдёт, вопрос можно пересмотреть: тогда в матрице обновятся строки «Нативные аддоны», «Развёртывание» и «Миграция».
Для проекта B Bun подходит при цели объединить инструментарий: один исполняемый файл закрывает рантайм, установку пакетов, тесты и сборку. Node.js остаётся допустимым вариантом после той же приёмки — сверки node:-модулей и прогона тестов. Выбор рантайма здесь не отменяет проверку типов отдельным шагом.
Порядок действий, который переносится на любой проект:
- Заполните матрицу по 11 критериям, указав для каждой строки источник проверки.
- Отделите строки, опирающиеся на документацию, от строк, требующих локального прогона.
- Выполните две проверки: сборку нативного аддона под Bun и прогон тестов через bun test со сверкой node:-модулей.
- Отметьте расхождения и обновите матрицу.
- Примите решение по проекту.
Выбранный способ сборки проекта описывает проект и не является ограничением всего рантайма. Строка матрицы «Бандлинг» фиксирует инструмент, который использует ваша сборка, и не говорит о возможностях Bun или Node.js за её пределами.
Частые вопросы
Bun полностью заменяет Node.js?
Документация Bun описывает рантайм как замену Node.js и заявляет стремление к полной совместимости с встроенными глобалами и модулями, называя эту работу продолжающейся. Справочник совместимости показывает статусы по каждому модулю: часть отмечена как полностью реализованная, часть — как частичная. Решение зависит от того, какие модули использует ваш проект.
Что делать с нативным аддоном при переходе на Bun?
Соберите аддон под Bun в отдельной ветке и зафиксируйте результат до решения о миграции. Сборка через node-gyp опирается на механизмы Node.js, поэтому её результат под Bun проверяется на месте. Пока проверка не выполнена, миграцию проекта с таким аддоном планировать рано.
Как проверить совместимость node:-модулей?
Выпишите все node:-модули проекта и найдите каждый в справочнике совместимости Bun. Рядом со статусом указаны известные отличия: например, для node:http отмечено, что http.Server не расширяет net.Server. Отметьте расхождения и решите, затрагивают ли они ваш код.
Подходит ли bun test для существующих тестов?
Тест-раннер Bun описан как Jest-совместимый и ориентированный на TypeScript. Прогоните тесты через bun test и сравните результат с прогоном на Node.js. Если проект использует node:test, учтите, что этот модуль отмечен как частично реализованный, и часть опций возвращает ERR_NOT_IMPLEMENTED.
Можно ли запускать TypeScript в Bun без сборки?
Bun выполняет файлы .ts и .tsx напрямую: транспайлер преобразует их в обычный JavaScript перед запуском. Проверка типов при этом остаётся отдельным шагом, для которого документация Bun перечисляет bun check. Запуск .ts и проверка типов — разные операции, и вторая не следует из первой автоматически.
