Bun совмещает несколько инструментов, которые обычно ставят по отдельности: среду выполнения JavaScript и TypeScript, пакетный менеджер, тест-раннер и сборщик. Он использует JavaScriptCore вместо V8, поэтому стартует быстрее и иначе работает с некоторыми нативными модулями. Для небольших сервисов, CLI и скриптов это удобно; для существующего Node-проекта сначала нужна проверка совместимости.
Установка и проверка
Официальный установщик кладёт бинарник в ~/.bun/bin и добавляет путь в профиль оболочки. Перед запуском скрипта из интернета полезно открыть его и прочитать, но для стандартной установки достаточно одной команды. Пакетные менеджеры дистрибутивов часто отстают от релизов, поэтому для разработки лучше официальный вариант.
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
bun --version
bun --revision
bun --revision печатает версию и хеш сборки — это помогает при сообщении об ошибке. Если команда не найдена, проверьте echo $PATH и перезапустите терминал. В CI установку фиксируют конкретной версией, чтобы сборка не менялась от неожиданного обновления.
Новый проект и TypeScript
bun init создаёт package.json, tsconfig.json и точку входа. TypeScript работает без отдельной компиляции: Bun транспилирует файлы на лету. Это не отменяет проверку типов — для неё нужен tsc --noEmit, иначе ошибки типов проявятся только в редакторе.
bun init -y
bun run index.ts
bun add -d typescript
bunx tsc --noEmit
В package.json скрипты запускаются через bun run. Для совместимости с инструментами, которые вызывают Node, можно принудительно использовать Bun как исполнитель: bun --bun run vite. Ключ --bun влияет на shebang и дочерние процессы, а не на совместимость пакетов.
Пакетный менеджер и lockfile
bun install читает package.json и создаёт текстовый bun.lock. В репозиторий коммитят lockfile, а node_modules исключают. Для воспроизводимой установки в CI используют --frozen-lockfile: при расхождении манифеста и lock-файла установка завершится ошибкой, а не тихо обновит зависимости.
bun install
bun add zod
bun add -d vitest
bun install --frozen-lockfile
Bun не запускает postinstall-скрипты пакетов без явного разрешения. Если пакету действительно нужен код установки, его добавляют в trustedDependencies в package.json или разрешают командой bun pm trust. Это снижает риск выполнения произвольного кода при установке, но требует внимательности: без postinstall некоторые нативные пакеты не соберутся.
bun pm ls --all
bun pm trust sharp
bun remove zod
bun outdated
Запуск, watch и разовые команды
Режим --watch перезапускает процесс при изменении файлов. Для серверной разработки этого достаточно, но для сложных сценариев с горячей заменой модулей лучше оставить специализированный dev-сервер. bunx запускает пакет без глобальной установки, как npx.
bun --watch run src/server.ts
bun run dev
bunx prisma generate
bun -e 'console.log(process.versions.bun)'
Флаг --smol уменьшает потребление памяти за счёт более частой сборки мусора. Он полезен в контейнерах с жёстким лимитом, но не является универсальным ускорением. Проверяйте поведение под нагрузкой, а не только на пустом приложении.
Тесты
Встроенный тест-раннер понимает Jest-подобный синтаксис и не требует отдельной конфигурации. Тесты импортируют test и expect из bun:test. Файлы ищутся по маскам *.test.ts, *.spec.ts и в каталоге __tests__.
import { test, expect } from "bun:test";
test("складывает числа", () => {
expect(1 + 2).toBe(3);
});
Запуск: bun test, покрытие: bun test --coverage, конкретный файл: bun test src/sum.test.ts. Для асинхронных тестов используйте async и await; таймауты задаются третьим аргументом. Встроенный раннер быстрый, но в проекте с готовой инфраструктурой Jest или Vitest миграция не всегда оправдана.
Сборка и компиляция
bun build собирает JavaScript для Node, браузера или самого Bun. Для CLI можно получить один исполняемый файл с встроенной средой выполнения: он не требует установленного Bun на целевой машине, но весит десятки мегабайт и собирается под конкретную платформу.
bun build ./src/index.ts --outdir ./dist --target node --minify
bun build ./src/index.ts --outdir ./dist --target browser
bun build ./src/cli.ts --compile --outfile mycli
./mycli --help
Кросс-компиляция для другой ОС и архитектуры задаётся через --target, но нативные зависимости всё равно нужно проверять на целевой платформе. Для библиотек публикуйте исходники и типы, а сборку оставьте потребителю; для приложения фиксируйте версию Bun в CI.
Встроенные API
Bun предлагает собственные модули, которые не нужно устанавливать: HTTP-сервер, SQLite, работа с файлами, хеширование паролей. Они удобны в небольших сервисах, но привязывают код к Bun. Если проект должен запускаться и в Node, используйте стандартные библиотеки и только потом добавляйте оптимизации.
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response("ok");
},
});
console.log(server.url);
bun:sqlite открывает базу одной строкой, Bun.file() лениво читает файл, Bun.password.hash() использует argon2id. Это не замена ORM и не отменяет миграции, но убирает лишние зависимости на старте проекта. Проверяйте, какие API доступны в вашей версии, по официальной документации, а не по статьям.
Совместимость и диагностика
Bun реализует большую часть node:-модулей и поддерживает N-API, но не все нативные аддоны и не все тонкости V8. Симптомы обычно выглядят как «пакет установился, но падает при импорте». Практическая проверка перед миграцией:
- сравните поведение проблемного пакета в Bun и Node;
- запустите тесты на той же версии, что в CI;
- зафиксируйте версию Bun в конфигурации сборки.
bun pm ls
bun install --verbose
bun --smol run src/server.ts
bun test --timeout 10000
Для поиска причины смотрите полный стек и версию пакета; --verbose показывает, откуда взялась зависимость. Если приложение работает в Node, но падает в Bun, изолируйте проблемный модуль небольшим тестом. Не отключайте проверки типов и не переносите весь проект сразу: начните со скриптов, тестов или отдельного сервиса.
Итог
Bun сокращает количество инструментов в проекте: установка, запуск TypeScript, зависимости, тесты и сборка доступны из одного бинарника. Начните с нового CLI или небольшого сервиса, зафиксируйте версию, проверьте нативные зависимости и добавьте bun test в CI. Для существующего Node-проекта сначала измерьте совместимость, а уже потом переносите код.