Как стать автором
Обновить

Релиз Bun 1.0 (новый runtime для JavaScript )

Уровень сложностиПростой
Время на прочтение12 мин
Количество просмотров37K
Автор оригинала: Jarred Sumner, Ashcon Partovi, Colin McDonnell

Представляем 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, которые реально имеют значение.

Полнофункциональные приложения, созданные с помощью Next.js, Remix, Nuxt, Astro, SvelteKit, Nest, SolidStart и Vite, работают в Bun.
Полнофункциональные приложения, созданные с помощью Next.js, Remix, Nuxt, Astro, SvelteKit, Nest, SolidStart и Vite, работают в Bun.

Скорость

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

Бан запускает "Hello, wolrd!" на TypeScript в 5 раз быстрее, чем Node.js с esbul.
Бан запускает "Hello, wolrd!" на TypeScript в 5 раз быстрее, чем Node.js с esbul.

В отличие от 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, которые досутупны в браузерах (fetchRequestResponseWebSocketи 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или .pngAPI плагинов основан на 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 раз больше сообщений в секунду, чем 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 в качестве среды выполнения, встроенный менеджер пакетов Bun может ускорить процесс разработки. Прошли те времена, когда вы смотрели, как долго выполняется установка зависимостей в npm.

Хотя Bun выглядит как привычные вам менеджеры пакетов:

bun install
bun add <package> [--dev|--production|--peer]
bun remove <package>
bun update <package>

Bun ощущается иначе!

Скорость установки

Bun на порядки быстрее, чем npmyarn, и pnpm. Он использует глобальный кеш модулей, чтобы избежать избыточных загрузок из реестра npm, и использует самые быстрые системные вызовы, доступные в каждой операционной системе.

Бенчмарк по установке зависимостей для стартового проекта Remix.
Бенчмарк по установке зависимостей для стартового проекта Remix.

Запуск скриптов

Скорее всего, вы давно не запускаете скрипт напрямую через node. Вместо этого мы часто используем менеджеры пакетов для взаимодействия с платформами и интерфейсами командной строки при разработке наших приложений.

npm run dev

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

npm run заметно лагает
npm run заметно лагает
bun run отрабатывает мгновенно
bun run отрабатывает мгновенно

И мы не просто придираемся к 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.

Объединение 10 копий Three.js с нуля, с исходными картами и минификацией
Объединение 10 копий Three.js с нуля, с исходными картами и минификацией

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 в телеграме про разработку и не только ;-)

Теги:
Хабы:
Всего голосов 74: ↑71 и ↓3+83
Комментарии118

Публикации

Истории

Работа

Ближайшие события

15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань