Bunとは？そしてBunのサーバーでクエリパラメーターを取得する方法

ハイサイ！オースティンやいびーん

# 概要

Bunのサーバーでリクエストからクエリパラメータをパースする方法を紹介します。

## Bunとは

BunはNode.jsに代わるJavaScriptのランタイム環境として開発されています。要は、Node.jsと同じようにブラウザでない環境でJavaScriptが実行できるようにするプラットフォームです。大体、**Node.jsと同じことをしています**。

NodeがV8をベースにして作られたのに対して、BunはWebKitを元に設計されています。

## BunとNodeの違い

まず念頭に言っておきたいのは、**Bunは速いのです**。以下の図でNext.jsのパフォーマンスを比較しているのですが、速いのがわかります。他のベンチマークでも軒並み速いんです。

![Screenshot 2023-05-24 at 8.45.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/b3aa62b6-a5ca-42fd-103b-2942318eb4b4.png)
_引用：[Bunホームページ](https://bun.sh/)_

パフォーマンスの良さはZig言語で書かれた拡張のおかげらしいです。ZigはRust等のようにメモリ等を直接コントロールできるCの後継者言語のようですが筆者は詳しくありません:sweat_smile:。

それが一番の違いのですが、他にも以下のような利点があります。

- ネイティブのESMサポート
- ESBuildより速いバンドラーがネイティブ機能として使える
- 優れたパッケージマネージャー
- ネイティブTypeScriptサポート
- ネイティブ環境変数ファイル`.env`サポート
- Web APIがブラウザと同様に実装されているのでブラウザで動くものはBunで問題なく動く


## BunはNode.jsのパッケージのほとんどをそのまま使えるようになっている

BunはNodeにない機能をあれこれ用意してくれているのですが、すぐ取り入れたいと思う方、あっぱれです。

残念ながら、筆者は新しい技術を受け入れるコストを重く見てしまうので、Bunに関しては最初、慎重だったのです。新しい何かを勉強するということは、確実にそれがいいもので今後も残るであろうことが確実になってからやるべきだと考えています。

そして、**Bunは今後も残りそうなので、一回は試すべき**だと最近思いました。

Bunを試してみるとわかりますが、非常にNode.jsのユーザーに優しく設計されているので、**学習コストが低いんです**。

Nodeでできていたことのほとんどがそのままできるし、ブラウザ標準に乗っ取ってAPIが実装されているから、**Nodeのように独特なAPIは少ないのです**。

その例として、サーバーの`Request`オブジェクトとクエリパラメーターの取得をこれから紹介しますが、**とてもブラウザらしいJavaScriptで気持ちがいいです**。

# Bunをインストールする

Homebrewでインストールするのは簡単です。

```
brew tap oven-sh/bun # for macOS and Linux
brew install bun
```

他のインストール方法はHPでご確認ください。

https://bun.sh/docs/installation

# Bunプロジェクトをセットアップ

プロジェクトのフォルダーを作ってそこに入りましょう。

```
mkdir Documents/practice/bun-quickstart
cd Documents/practice/bun-quickstart
```

そしてBun CLIを使って`package.json`等の初期設定を行います。

```
bun init
```

プロンプトに従ってあれこれ設定できます。
![Screenshot 2023-05-24 at 8.59.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/e4552f7e-f4d7-f76d-ec70-323b1abf472b.png)

# `Bun.serve` で簡単なWebサーバーを実装する

Bunでサーバーを作るのはNodeと同様に簡単です。グローバルオブジェクトの`Bun`をインポートする必要はなく、`Bun.serve`だけで実装できます。

```typescript:index.ts

console.log("Hello via Bun!");

Bun.serve({
  port: 3000,
  async fetch(request, server) {
    return new Response('Hello World');
  },
});
```

`Response`は[ECMAScript標準のResponse](https://developer.mozilla.org/en-US/docs/Web/API/Response)オブジェクトそのもの、`fetch`から返ってくる`Response`と一緒なのです。

# クエリパラメーターをRequestから取得する

ここで、筆者はクエリパラメーターを取得したいなと思いましたが、`request`にそれらしいプロパティはなく、困惑しました。そこで以下の事実を改めて実感しました。

**Bunはあくまでも標準的なJavaScriptを実装しているのです**。

そしたら、ブラウザでクエリパラメーターをどうやって取得するかというと、`URL`のAPIを使いますよね。**Bunでもそのような考え方が通じるっぽいんです**。

```typescript:index.ts
Bun.serve({
  port: 3000,
  async fetch(request, server) {
    const { searchParams } = new URL(request.url);
    return new Response(searchParams.getAll('referrer'));
  },
});
```

これでsearchParams、つまりクエリパラメーターを取得することができます。

# 試してみる

試してみましょう。以下のコマンドを実行してサーバーを立ち上げます。

```
bun run index.ts
```

自動でTypeScriptをコンパイルしてくれるので、`node-ts`をインストールする必要はないです:heart_eyes:

`http://localhost:3000/?referrer=google&referrer=bing`でリクエストを送ってみましょう。

![Screenshot 2023-05-24 at 9.08.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/0175a1ce-e5de-22ee-631b-e9f462c75401.png)

ホウホウ。うまくいきました。

# まとめ

Bunを紹介して、Bunらしい考え方でクエリパラメーターを取得する方法も説明しましたが、いかがでしょうか？

筆者は、Bunが面白そうなので、今後もあれこれ遊んでみたいと思っています！