Что такое Bun, новая горячая штучка в мире Javascript? Почему это так быстро и могу ли я использовать его для своих проектов?

В последние годы ландшафт веб-разработки обнаружил, что, хотя суперстилизованные веб-сайты и веб-приложения с множеством очень богатых взаимодействий, сделанных с помощью Javascript, могут быть привлекательными для пользователей, время загрузки страницы может в сто раз больше влиять на пользователя. перспектива опыта. В результате было приложено много усилий, чтобы уменьшить показатели времени загрузки веб-сайтов. Для решения этой проблемы появилось (повторно) множество фреймворков и шаблонов, таких как рендеринг на стороне сервера и создание статического сайта.

Входит Джарред Самнер. Джарред заметил, что такое простое действие, как вывод на консоль, выполнялось в Node.js очень медленно. Вот пример времени, необходимого для выполнения программы «Hello world» в Node.js и Rust.

log.js

console.log('Hello world!')
$ time node log.js
Hello world!
node log.js  0,13s user 0,02s system 100% cpu 0,152 total

log.rs

fn main() {
  println!("Hello world!");
}
$ rustc log.rs
$ time ./log
Hello world!
./log  0,00s user 0,00s system 86% cpu 0,004 total

Джарред сказал, что его очень беспокоил этот факт, а также другие реалии мира Javascript, такие как необходимость выбирать и согласовывать несколько инструментов — среду выполнения, сборщик, транспилер… Он был уверен, что это не обязательно должно быть так. и он отправился в путешествие в одиночку, чтобы построить Бан.

Что такое Бун?

Bun — это прежде всего среда выполнения Javascript, такая как Node.js и Deno. Он предназначен для исключительно быстрой среды выполнения Javascript. Но не волнуйтесь, использование этой новой среды выполнения не означает необходимость рефакторинга всего вашего существующего кода. Bun реализует большинство API-интерфейсов Node и веб-API, таких как fs, fetch, Buffer, WebSocket и многие другие. Кроме того, Bun также совместим с большинством пакетов NPM, несмотря на то, что он использует собственный менеджер пакетов, который, опять же, создан для повышения скорости.

Но Bun — это не просто среда выполнения Javascript, она поставляется с включенными батареями. Он поставляется со всеми инструментами, которые обычно необходимы в проекте Javascript: менеджер пакетов, упаковщик и транспилятор, который работает не только с Javascript, но и с готовыми работами с Typescript и JSX. Кроме того, он также включает встроенную реализацию для загрузки конфигурации dotenv и клиента SQLite3.

Вот пример установки package.json обычного размера с использованием NPM v8.15 и диспетчера пакетов Bun v0.1.5:

$ time npm install
added 563 packages, and audited 564 packages in 3m
npm install  166,14s user 16,06s system 92% cpu 3:16,08 total
$ bun install
bun install v0.1.5
 563 packages installed [9.70s]

Но как Бан так быстро?

Скорость Bun можно объяснить двумя основными факторами: выбором движка Javascript и низкоуровневой оптимизацией нативных реализаций.

И Node.js, и Deno используют движок Javascript V8. Хотя V8 — отличный движок, на котором работает веб-браузер Chrome, Бан выбрал вариант, который обеспечил бы наилучшую производительность любой ценой. Джарред решил использовать механизм JavascriptCore для создания Bun, который представляет собой движок, лежащий в основе Webkit, и кажется, что он работает лучше во время запуска, а также в некоторых конкретных случаях.

Еще одно решение, которое помогло максимально оптимизировать Bun, — это выбор Zig в качестве языка, на котором он построен. Zig — это низкоуровневый язык программирования без сборщика мусора, такой как C или Rust. Хотя эти два языка могли бы стать отличным выбором для создания Бана, у Zig есть несколько уникальных особенностей, которые ценил Джарред, что в конечном итоге привело к тому, что он предпочел Zig другим языкам. Во-первых, Zig не имеет скрытого потока управления, что упрощает обеспечение того, чтобы никакие второстепенные функции не вызывались неожиданно при его запуске. Кроме того, в Zig есть функция CompTime. С CompTime вы можете пометить фрагмент кода для выполнения во время компиляции, а не во время выполнения, экономя любое драгоценное время, которое можно вычеркнуть из окончательного времени выполнения.

Использование булочки

Чтобы использовать Bun, сначала установите его с помощью следующей команды:

curl https://bun.sh/install | bash

Да, это команда оболочки. Нет, (на момент написания этой статьи) он не работает для Windows. Теперь вы можете начать использовать Bun.

В этом примере мы создадим веб-сервер. Бан поставляется с готовым HTTP-сервером. Если файл, используемый для запуска bun, имеет экспорт по умолчанию с функцией выборки, он запустит HTTP-сервер, но вы также можете использовать Bun.serve() для ясности. Вот простой пример:

http.ts

export default {
  port: 3000,
  fetch(request: Request): Response {
    return new Response("Hello world!");
  }
};

Обратите внимание, что для этого примера библиотека не нужна. И Typescript, и HTTP-сервер просто работают. Теперь давайте запустим код и проверим, что сервер запущен и работает:

$ bun run http.ts
$ curl http://localhost:3000
Hello world!

Отличный! Теперь мы можем представить новые функции на сервере. Мы могли бы использовать улучшенный API Node.js для чтения и возврата содержимого файла. Мы также можем использовать встроенный клиент SQLite для извлечения записей из базы данных. Используя инструменты, которые предоставляет Бан, мы можем легко реализовать это:

import {
  readFileSync
} from 'fs';
import {
  Database
} from 'bun:sqlite';
export default {
  port: 3000,
  async fetch(request: Request): Promise<Response> {
    const urlParts = request.url.match(/https?:\/\/.+\/(.*)/);
    const [_, resource] = urlParts;
    if (resource === 'file') {
      const file: string = readFileSync('/home/roger/Projects/experiments/log/file.txt', { encoding: 'utf-8' });
      return new Response(file);
    }
    else if (resource === 'db') {
      const db = new Database('db.sqlite');
      const query = db.query('SELECT * FROM foo');
      const result = query.run();
      db.close();
      return new Response(result);
    }
    return new Response('Hello world!');
  }
};

Для чего я могу использовать Бун?

Давайте проясним: Bun не готов для рабочих приложений. На момент написания этой статьи последней версией Bun была бета-версия 0.1.5. Он по-прежнему имеет небольшую экосистему и сообщество, множество отсутствующих API, а также некоторые ошибки и проблемы с производительностью в крайних случаях. Тем не менее, это временная проблема; Джарред и сообщество неустанно работают над созданием всех недостающих инструментов и API и исправлением всех ошибок. Когда я впервые писал эту статью, я описал некоторые проблемы, такие как скачки производительности и недопустимые аппаратные инструкции. Но эти проблемы решаются так быстро, что эта статья была бы постоянно устаревшей. Также постоянно появляются библиотеки, созданные специально для Bun. Вероятно, в недалеком будущем Bun станет отличным инструментом для использования в производственных средах, поэтому было бы разумно следить за ним.

Это не значит, что вы не должны использовать Бан прямо сейчас. Если вам нужно создать приложение, не зависящее от рабочей среды, это может быть подходящим вариантом. Если вы хотите создать быстрое приложение для проверки концепции и не хотите возиться с библиотеками Typescript и транспилеров, это может быть отличным решением. Другое возможное использование может быть, если вам нужно написать скрипт, который должен работать в лучшем виде, и вам не нужно писать его на Rust или C.

В заключение, следите за Бун. То, что Джарред создал всего за год, уже оказало большое влияние на сообщество Javascript и может полностью изменить его.