Представляем 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
Bun — универсальный набор инструментов
Мы любим 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.
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" };
});
},
});
Собственные APIs
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 раз больше сообщений в секунду, чем
ws
Node.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 в качестве среды выполнения, встроенный менеджер пакетов 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🚀 |
Bun - тест раннер
Если вы раньше писали тесты на 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 в качестве сборщика
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 в телеграме про разработку и не только ;-)
Автор: Александр Русаков