Релиз Bun 1.0 (новый runtime для JavaScript )
- понедельник, 11 сентября 2023 г. в 00:00:15

Представляем Bun версии 1.0.
Bun — это быстрый универсальный набор инструментов для запуска, сборки, тестирования и отладки JavaScript и TypeScript кода (от одного файла до fullstack-приложения). Сегодня Bun стабилен и готов к продакшену.
Установка Bun
# curl
curl -fsSL <https://bun.sh/install> | bash
# npm
npm install -g bun
# brew
brew tap oven-sh/bun
brew install bun
# docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bunОбновление Bun
bun upgradeМы любим JavaScript. Он зрелый, быстро развивается, а его сообщество разработчиков активно и увлеченно. Это потрясающе.
Однако, с момента появления Node.js прошло 14 лет. Все эти годы доступные инструменты накапливались слой за слоем. И как любая система, которая растет и развивается без централизованного планирования, инструменты JavaScript стали медленными и сложными.
Почему Bun существует?
Цель проста - устранить медлительность и сложность, НЕ отказываясь при этом от всего хорошего в JavaScript. Ваши любимые библиотеки и фреймворки должны работать по-прежнему. Вам не придется отказываться от привычек.
Однако вам придется позабыть множество инструментов, которые Бан делает ненужными:
Node.js. Bun полностью заменяет Node.js, поэтому вам не нужно:
node
npx - bunx в 5 быстрее
nodemon — Bun имеет встроенный watch-режим
dotenv, cross-env - Bun читает .env файлы по умолчанию
Транспиляторы. Bun может запускать .js, .ts, .cjs, .mjs, .jsxи .tsxфайлы, заменяя собой:
tsc — (но вы можете сохранить его для проверки типов!)
babel, .babelrc, @babel/preset-*
ts-node, ts-node-esm
tsx
Бандлеры. Bun — это сборщик JavaScript с лучшей производительностью и совместимым с esbuild API плагинов, поэтому вам не нужны больше:
esbuild
webpack
parcel, .parcelrc
rollup, rollup.config.js
Менеджеры пакетов . Bun является npm-совместимым менеджер пакетов со знакомыми командами. Он читает ваш файл package.jsonи записывает зависимости в node_modules, как и другие менеджеры пакетов:
npm, .npmrc, package-lock.json
yarn, yarn.lock
pnpm, pnpm.lock, pnpm-workspace.yaml
lerna
Библиотеки для тестирования. Bun можно использовать в качестве Jest-совместимого тест-раннера с поддержкой снапшотов, моков и code coverage, поэтому вам больше не нужны:
jest, jest.config.js
ts-jest, @swc/jest, babel-jest
jest-extended
vitest, vitest.config.ts
Хотя каждый из этих инструментов хорош сам по себе (в основном), их совместное использование неизбежно приводит к нестабильности и замедлению процесса разработки. Они выполняют много избыточной работы; при запуске jestваш код будет распаршен различными инструментами более 3 раз! А плагины и адаптеры (а иногда изолента со скотчем 😆), необходимые для совместной работы всего вместе, со временем изнашиваются.
Bun — это единый и интегрированный набор инструментов, позволяющий избежать этих проблем. Каждый инструмент в этом наборе обеспечивает лучшие в своем классе возможности для разработчиков — от производительности до удобства API.
Bun — это быстрая среда выполнения JavaScript. Его цель — сделать процесс создания программного обеспечения более быстрым, менее утомительным и более увлекательным.
Совместимость с Node.js
Bun — это полная замена Node.js. Это означает, что существующие приложения Node.js и пакеты npm просто работают в Bun. Bun имеет встроенную поддержку Node.js APIs, в том числе:
встроенные модули, такие как fs, path и net
глобальные переменные, такие как __dirname и process
алгоритм разрешения зависимостей из node_modules
Хотя идеальная совместимость с Node.js невозможна (из-за наличия, например, модуля node:v8- https://nodejs.org/docs/latest-v20.x/api/v8.html), Bun может запускать практически любое приложение Node.js.
Bun тестируется на наборах тестов самых популярных пакетов Node.js из регистра npm. Серверные платформы, такие как Express, Koa и Hono, просто работают. Как и приложения, созданные с использованием самых популярных фулстек фреймворков. В совокупности эти библиотеки и фреймворки затрагивают все части Node.js API, которые реально имеют значение.

Скорость
Bun работает быстро: запускается в 4 раза быстрее , чем Node.js. Эта разница только увеличивается, если речь идет о запуске TypeScript, который требует транспиляции, прежде чем Node.js сможет его запустить.

В отличие от Node.js и других сред выполнения, созданных с использованием движка V8 от Google, Bun создан с использованием движка WebKit (разработку которого начинали внутри Apple). WebKit — это движок, лежащий в основе Safari и использующийся миллиардами устройств каждый день. Он быстрый, эффективный и проверенный десятилетиями.
Примечание переводчика. Стоит еще добавить, что bun во основном написал на молодом языке программирования Zig (еще сам не дошел до версии 1.0). Zig претендует на туже нишу высокопроизводительного и системного программирования, что и C/C++ и с недавних пор Rust.
Поддержка TypeScript и JSX
В Bun транспилятор встроен в среду выполнения. Это означает, что вы можете запускать файлы JavaScript, TypeScript и даже JSX/TSX без каких-либо дополнительных инструментов.
bun index.t
# or
bun index.tsxСовместимость ESM и CommonJS
Переход от модулей CommonJS к ES-модулям был медленным и тяжелым. После появления ESM Node.js потребовалось 5 лет до поддержки без --experimental-modulesфлага. Несмотря на это, экосистема по-прежнему полна CommonJS.
Bun поддерживает обе модульные системы одновременно. Не нужно беспокоиться о расширениях файлов (.js, .cjs, .mjs), или о "type": "module" в package.json.
Вы даже можете использовать importи require()в одном и тоже файле. Это просто работает.
import lodash from "lodash";
const _ = require("underscore")Веб-API
Bun имеет встроенную поддержку Web APIs, которые досутупны в браузерах (fetch, Request, Response, WebSocketи ReadableStream).
const response = await fetch("<https://example.com/>");
const text = await response.text()Вам больше не нужно устанавливать такие пакеты, как node-fetchи ws. Встроенные Web APIs реализованы в Bun в нативном коде, работают быстрее и надежнее, чем сторонние альтернативы.
Hot reloading
Bun облегчает работу разработчика. Вы можете запустить Bun с аргументов --hot, что включает hot reloading, которая перезагружает ваше приложение при изменении файлов.
bun --hot server.tsВ отличие от инструментов, которые принудительно перезапускают весь процесс, например nodemon, Bun перезагружает ваш код, не завершая старый процесс. Это означает, что соединения HTTP и WebSocket не разрываются, состояния не теряются.
Гифка про hot reloading лежит тут - https://bun.sh/hot.gif
Плагины
Bun спроектирован с учетом кастомизации.
Вы можете использовать плагины для перехвата импорта и выполнения собственной логики загрузки. Плагин может добавить поддержку дополнительных типов файлов, таких как .yamlили .png. API плагинов основан на esbuild, а это означает, что большинство плагинов esbuild будут работать в Bun из коробки:
import { plugin } from "bun";
plugin({
name: "YAML",
async setup(build) {
const { load } = await import("js-yaml");
const { readFileSync } = await import("fs");
build.onLoad({ filter: /.(yaml|yml)$/ }, (args) => {
const text = readFileSync(args.path, "utf8");
const exports = load(text) as Record<string, any>;
return { exports, loader: "object" };
});
},
});
Bun поставляется с оптимизированной стандартной библиотеки состоящий из самого необходимого.
В отличие от API Node.js, которые существуют для обратной совместимости, эти нативные Bun APIs разработаны таким образом, чтобы быть быстрыми и простыми в использовании.
Bun.file()
Используйте Bun.file()для ленивой загрузки файла пути.
const file = Bun.file("package.json");
const contents = await file.text();Функция возвращает объект BunFile, расширяющий веб-стандарт File. Содержимое файла можно загружать в различных форматах.
const file = Bun.file("package.json");
await file.text(); // string
await file.arrayBuffer(); // ArrayBuffer
await file.blob(); // Blob
await file.json(); // {...}Bun читает файлы в 10 раз быстрее , чем Node.js.
Bun.write()
Bun.write()— это единый гибкий API для записи на диск практически всего — строк, двоичных данных, блобов и даже Responseобъектов.
await Bun.write("index.html", "<html/>");
await Bun.write("index.html", Buffer.from("<html/>"));
await Bun.write("index.html", Bun.file("home.html"));
await Bun.write("index.html", await fetch("<https://example.com/>"));Bun записывает файлы в 3 раза быстрее , чем Node.js.
Bun.serve()
С помощью Bun.serve() можно запустить HTTP-сервера, WebSocket-сервер или оба сервера одновременно. Он основан на знакомых Web-стандартных API, таких как Requestи Response.
Bun.serve({
port: 3000,
fetch(request) {
return new Response("Hello from Bun!");
},
});Bun может обслуживать в 4 раза больше запросов в секунду, чем Node.js.
Вы также можете настроить TLS, используя эту tlsопцию.
Bun.serve({
port: 3000,
fetch(request) {
return new Response("Hello from Bun!");
},
tls: {
key: Bun.file("/path/to/key.pem"),
cert: Bun.file("/path/to/cert.pem"),
}
});Для поддержки WebSockets наряду с HTTP достаточно определить обработчик событий внутри свойства websocket. В Node.js для этого же приходиться устанавливать стороннюю зависимость, например, ws, потому что встроенной поддержки WebSocket нет.
Bun.serve({
fetch() { /* ... */ },
websocket: {
open(ws) { /* ... */ },
message(ws, data) { ... },
close(ws, code, reason) { ... },
},
});Bun может обрабатывать в 5 раз больше сообщений в секунду, чем
wsNode.js.
bun:sqlite
Bun имеет встроенную поддержку SQLite. API вдохновлено better-sqlite3, но реализовано в нативном коде и работает быстрее.
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const query = db.query("select 'Bun' as runtime;");
query.get(); // => { runtime: "Bun" }Бан может выполнять запросы к SQLite до 4 раз быстрее , чем
better-sqlite3в Node.js.
Bun.password
Bun также поддерживает API для распространенных, но сложных вещей, которые вы не захотите реализовывать самостоятельно.
Вы можете использовать Bun.passwordдля хэширования и проверки паролей с помощью bcrypt или argon2, без каких-либо внешних зависимостей.
const password = "super-secure-pa$$word";
const hash = await Bun.password.hash(password);
// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bfPxQdh...
const isMatch = await Bun.password.verify(password, hash);
// => trueДаже если вы не используете Bun в качестве среды выполнения, встроенный менеджер пакетов Bun может ускорить процесс разработки. Прошли те времена, когда вы смотрели, как долго выполняется установка зависимостей в npm.
Хотя Bun выглядит как привычные вам менеджеры пакетов:
bun install
bun add <package> [--dev|--production|--peer]
bun remove <package>
bun update <package>Bun ощущается иначе!
Скорость установки
Bun на порядки быстрее, чем npm, yarn, и pnpm. Он использует глобальный кеш модулей, чтобы избежать избыточных загрузок из реестра npm, и использует самые быстрые системные вызовы, доступные в каждой операционной системе.

Запуск скриптов
Скорее всего, вы давно не запускаете скрипт напрямую через node. Вместо этого мы часто используем менеджеры пакетов для взаимодействия с платформами и интерфейсами командной строки при разработке наших приложений.
npm run devВы можете заменить npm runна bun run, что сэкономит 150 миллисекунд при каждом запуске команды. Это ускорение может показаться небольшим, но при использовании CLI разница в восприятии огромна.


И мы не просто придираемся к npm. bun run <command> быстрее эквивалентов и в yarn, и в pnpm.
Команда | Среднее время |
|---|---|
npm run | 176ms |
yarn run | 131ms |
pnpm run | 259ms |
bun run | 7ms🚀 |
Если вы раньше писали тесты на JavaScript, то, скорее всего, знакомы с Jest, который стал пионером API-интерфейсов в стиле «expect». (Как будто были и другие пионеры, кто активно предлагал expect-стиль тестирования. Примечание переводчика)
Bun имеет встроенный модуль тестирования bun:test, который полностью совместимый с Jest.
import { test, expect } from "bun:test";
test("2 + 2", () => {
expect(2 + 2).toBe(4);
});Вы можете запустить свои тесты с помощью bun testкоманды. Также вы получаете все преимущества среды выполнения Bun, включая поддержку TypeScript и JSX.
Миграция с Jest или Vitest проста. Любой импорт из @jest/globalsили vitestбудет подменен на импорт из bun:test, поэтому все работает даже без изменений кода.
// index.test.ts
import { test } from "@jest/globals";
describe("test suite", () => {
// ...
});В бенчмарке при тестировании zod Bun быстрее в 13 раз, чем Jest, и в 8 раз быстрее, чем Vitest.

Матчеры Bun реализованы в быстром нативном коде, поэтому expect().toEqual() в Bun в 100 раз быстрее , чем Jest, и в 10 раз быстрее, чем Vitest.
Для начала вы можете ускорить работу CI с помощью bun test. В Github Actions используйте oven-sh/setup-bun.
# .github/workdlows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: oven-sh/setup-bun@v1
- run: bun testА чтобы сделать работу еще приятнее, Bun автоматически добавляет аннотации к неудачным тестам, чтобы логи CI было легче читать.

Bun может выступать и как сборщик и минификатор JavaScript и TypeScript код, который можно для браузера, Node.js и других платформ.
bun build ./index.tsx --outdir ./build
Он во многом вдохновлен esbuild и предоставляет совместимый API для плагинов.
import mdx from "@mdx-js/esbuild";
Bun.build({
entrypoints: ["index.tsx"],
outdir: "build",
plugins: [mdx()],
});
В Bun API плагинов является универсальным, то он работает как для сборщика, так и для среды выполнения. Таким образом плагин для обработки .yaml, о котором шла речь раньше, можно использовать здесь для поддержки импорта .yaml файлов во время сборки.
Согласно собственным тестам esbuild, Bun в 1,75 раза быстрее, чем esbuild, в 150 раз быстрее, чем Parcel 2, в 180 раз быстрее, чем Rollup + Terser, и в 220 раз быстрее, чем Webpack.

Cреда выполнения и сборщик Bun интегрированы, а это означает, что Bun может делать то, чего не может сделать ни один другой сборщик.
Бан представляет макросы JavaScript — механизм запуска функций JavaScript во время сборки . Значение, возвращаемое этими функциями, напрямую встраивается в ваш пакет.
// index.ts
import { getRelease } from "./release.ts" with { type: "macro" };
// The value of release is evaluated at bundle-time,
// and inlined into the bundle, not run-time.
const release = await getRelease();
// release.ts
export async function getRelease(): Promise<string> {
const response = await fetch(
"<https://api.github.com/repos/oven-sh/bun/releases/latest>"
);
const { tag_name } = await response.json();
return tag_name;
}
После вызова bun build index.ts мы получим:
var release = await "bun-v1.0.0"Это новая парадигма объединения JavaScript, и мы с нетерпением ждем возможности увидеть, что вы с ее помощью создадите.
Bun предоставляет сборки для macOS и Linux, но есть одно заметное отсутствие: Windows. Раньше, чтобы запустить Bun в Windows, вам нужно было установить подсистему Windows для Linux... но теперь это не так.
Впервые мы рады представить экспериментальную сборку Bun для Windows.

В то время как сборки Bun для macOS и Linux готовы к продакшен, сборка для Windows носит весьма экспериментальный характер . На данный момент поддерживается только среда выполнения JavaScript; менеджер пакетов, средство запуска тестов и сборщик отключены до тех пор, пока они не станут более стабильными. Производительность также не была оптимизирована (но это пока).
В ближайшие недели мы будем быстро улучшать поддержку Windows. Если вам нравится Bun для Windows, мы рекомендуем вам присоединиться к #windowsканалу на нашем Discord для получения обновлений.
Путешествие к версии 1.0 было бы невозможным без замечательной команды инженеров и растущего сообщества.
Мы хотели бы поблагодарить тех, кто помог нам дойди до этого момента:
Node.js и его контрибьютеры. Программное обеспечение построено на плечах гигантов.
WebKit и его контрибьютеры, особенно Constellation. Спасибо, что делаете WebKit быстрее. Вы потрясающие.
Почти 300 участников, которые помогали создавать Bun последние два года!
Bun 1.0 — это только начало.
Мы разрабатываем новый способ развертывания JavaScript и TypeScript в продакшен. И мы нанимаем системных инженеров, если вы хотите помочь нам построить будущее JavaScript.
Вы также можете:
Присоединится к нашему Discord, чтобы узнавать последние новости о Bun
Следить за нами в X/Twitter, чтобы получать мемы о JavaScript и ежедневные новости от Джареда и его команды
Поставьте нам звезду на Github — это окупит расходы! (/сарказм)
Журнал изменений с версии 0.8
Если вы использовали Bun ДО версии 1.0, то вот что изменилось.
Next.js, Astro и Nest.js теперь поддерживаются!
Устаревшая команда bun dev была уделена. Теперь bun dev запускает скрипт в вашем package.json
Bun теперь поддерживает следующие Node.js APIs:
child_process.fork() и IPC
fs.cp() и fs.cpSync()
fs.watchFile() и fs.unwatchFile()
Unix-сокеты в формате node:http
Горячая перезагрузка теперь поддерживает Bun.serve(). Раньше это работало только в случае, если сервер был определен через default export. Теперь корректно работает запуск bun --hot server.ts:
// server.ts
Bun.serve({
fetch(request) {
return new Response("Reload!");
},
})P.S. После прочтения данной новости пошел проверять на текущих проектах. Действительно, использование bun run проходит без каких-либо ошибок, то есть eslint, typescript, cspell, prettier, jest - работают без проблем. Ускорение в целом наблюдаю, но это проценты (до 50%), а не разы. Перейти на burn test - уже сложнее, если конфиги jest / ts отличаются от дефолтных наличием всяких modulePaths, baseUrl, paths и так далее. Про замену самого рантайма и Docker-ов пока ничего сказать не могу, но тут метрики скажут все сами за себя, когда руки дойдут.
Веду канал Alex Code в телеграме про разработку и не только ;-)