[JavaScriptランタイム] Bun v0.3.0の変更点についてざっくりと

2022.12.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

先日、高速なJavaScriptランタイムであるBunがバージョンアップアップしました。
バグフィックスに加え、いくつか新機能も追加されたので試してみます。

※以前のBun紹介記事はこちら

Environment

  • MacBook Pro (13-inch, M1, 2020)
  • OS : MacOS 12.4

Setup

Bunをインストールしていない方はインストールしましょう。
ここに以前おこなったインストール方法も書いてあります

curlで簡単にインストール可能。  

% curl -fsSL https://bun.sh/install | bash

すでにインストールしてある方はupgrade。

% bun upgrade

バージョン確認。

% bun --version
0.3.0

Changes in Bun 3.0

詳細はこちらにありますが、
ざっと解説していきます。

メモリ効率が向上

高負荷時のメモリ使用量が以前の1/4以下になりました。
イベントループ処理に合わせてGCを適切に実行するようにしたので性能が向上したとのこと。

Bunメモリパフォーマンス

console.logの改良とconsole.write

Bunのconsole.log()のフォーマットが改善され、
詳細な情報を表示するようになりました。

また、consoleがAsyncIterable(Iterableの非同期版)になり、
↓のように標準入力からテキスト行をストリームしてawaitループすることが可能に。

//console.ts
for await (const line of console) {
  console.log("Received:", line);
}
% bun console.ts
hello #入力
Received: hello

bun! #入力
Received: bun!

さらに、標準出力に書き込むためにconsole.write()を使うこともできるようになったとのこと。

console.write("hello");
console.write(["hello", "world", "\n"]);

const response = await fetch("https://example.com/");
console.write(["Response: ", await response.arrayBuffer()]);

その他、多数のAPIのバグフィックスや実装などがされてます。
bun:testのexpectについてもかなり多く実装されて高速化もされてます。

npmからの自動パッケージインストール機能

事前にパッケージをインストールしていなくても(node_modulesがなくても)、
importのときにnpmから自動的にパッケージをインストールできるようになりました。
セキュリティのため、postinstall(インストール後に実行されるスクリプト)は
実行されないので注意。

npm installとかbun addせずにexpressを使うコードを記述。

//bun-example.ts
import express_package from 'express/package'
console.log(express_package.version);

node_modulesなしで実行してもOK。

% rm -Rf node_modules
% bun bun-example.js
4.18.2

特定バージョンのパッケージを指定したい場合、
package.jsonで指定するかimportのパスに範囲指定子を記述します。
この範囲指定子は、package.jsonが存在しない場合にのみサポートされるとのこと。

@でバージョン指定。

//bun-example.ts
import express_package from 'express@4.17.0/package'
console.log(express_package.version);

指定したバージョンが使えます。

% rm package.json

% bun bun-example.js
4.17.0

この機能はBunがnode_modulesをサポートしなくなったわけでないのでご安心を。
自動インポートを無効にしたい場合は、--no-installフラグを使います。

% bun --no-install bun-example.js

error: Could not resolve: "express@4.17.0/package". Maybe you need to "bun install"?
import express_package from 'express@4.17.0/package'
                            ^

FileSystemRouter

パスを解決するための便利なAPIが追加されました。
これは、Webフレームワークとかでよく使う
Router(URLとファイルパスをマッチさせるやつ)みたいな機能です。
FileSystemRouterを作成し、Routerに対して
パスやリクエストを高速に処理することが可能になります。

次のような階層のディレクトリがあるとします。

% tree
.
├── main.ts
└── pages
    ├── foo.ts
    ├── hoge
    │   ├── bar.ts
    │   └── index.ts
    └── index.ts

main.tsで、FileSystemRouterを初期化してつかってみます。

//main.ts
import { FileSystemRouter } from "bun";

const router = new FileSystemRouter({
  dir: import.meta.dir + "/pages",
  style: "nextjs",
});

/* /index.tsにマッチ */
console.log(router.match("/"));

/* /hoge/index.tsにマッチ */
console.log(router.match("/hoge"));

/* /hoge/bar.tsにマッチ */
console.log(router.match("/hoge/bar?x=y"));

パスにマッチすると、MatchedRouteが返されます。
なお、index.tsがないと/hogeはマッチしません。
この処理はネイティブコードで実装されているのでとても高速とのこと。

現在サポートされているスタイルはnextjsのみとのことですが、
将来は他のスタイルもサポートする予定になってます。

Summary

Bunのv0.3について簡単に紹介しました。
着実に機能追加されてますね。

References