Bun がフロントエンド開発でかなり便利になりそう
皆さんご存知の JavaScript ランタイム兼開発ツールの Bun
が、v1.2.3 でフロントエンド開発のための便利な機能が使えるようになったので取り急ぎ。
現時点(2025/02/06)では Canary build なので試す方は以下のコマンドを実行してください。
bun upgrade --canary
Bun でビルドした実際に動作する React + Tailwind CSS の SPA の URL を貼っておきます。
https://github.com/harumaxy/bun-as-bundler)
(repo:開発サーバー機能
bun
コマンドで引数に HTML ファイルを指定すると、開発サーバーが立ち上がります。
touch index.html
<html>
<body>
Hello world
</body>
</html>
bun index.html
# ➜ http://localhost:3000/
バンドラー
CSS, JavaScript などのモジュールを HTML ファイルにバンドルすることが出来ます。
Tailwind CSS を使う
まず Tailwind CSS を試してみます。
package.json を初期化して、 bun-plugin-tailwind
をインストールします。
bun init -y
bun add -D bun-plugin-tailwind
# 必要なファイルを作成
touch bunfig.toml style.css
bunfig.toml
にプラグインを使う設定を書き、Tailwind をインポートした CSS を用意して head タグ内でロードします。
[serve.static]
plugins = ["bun-plugin-tailwind"]
@import "tailwindcss";
...
+ <head>
+ <link rel="stylesheet" type="text/css" href="./style.css" />
+ </head>
+ <body class="bg-slate-600 flex items-center justify-center">
+ <div class="text-3xl font-bold text-lime-400">
+ This is tailwind styled text
</div>
</body>
...
そして、開発サーバーを立ててページを開くと Tailwind CSS のスタイルが適用されています。
UIフレームワークを使う (React)
まずは NPM パッケージをインストール。
bun add react react-dom
bun add -D @types/react @types/react-dom
簡単な React コンポーネントを src/index.tsx
ファイルに書きます。
import * as React from "react";
import { createRoot } from "react-dom/client";
function App() {
const [spin, setSpin] = React.useState(false);
return (
<div>
<h1 className={`${spin ? "animate-spin" : ""} text-rose-400`}>
Hello from React
</h1>
<button
className="bg-indigo-400 text-white rounded-md p-2"
onClick={() => setSpin(!spin)}>
Toggle Spin
</button>
</div>
);
}
createRoot(document.getElementById("app")!).render(<App />);
そして、 HTML ファイルの <script>
タグで相対パス指定するだけで読み込む事ができます。
...
<body class="bg-slate-600 flex items-center justify-center">
<div class="text-3xl font-bold text-lime-400">
This is tailwind styled text
+ <div id="app"></div>
</div>
+ <script src="./src/index.tsx"></script>
</body>
...
React を簡単に使用することが出来ました!
(他のライブラリ・フレームワークも同様に可能)
SPA をビルドする
とりあえず React + Tailwind を使った Single Page Application を開発するボイラープレートが出来たので、これらを静的な HTML+CSS+JavaScript にバンドルしてみます。
通常は bun build index.html
でもできるのですが、 Tailwind を使用しているため、ビルドスクリプトを書くことでプラグインを適用しつつバンドルします。
touch build.ts
import BunPluginTailwind from "bun-plugin-tailwind"
await Bun.build({
entrypoints: ["index.html"],
outdir: "dist",
plugins: [BunPluginTailwind]
})
bun run build.ts
# HTMLファイルを serve して確認 -> http://localhost:3000
bunx serve dist
余談: MPA ビルド
最近は React Router とかで SPA でも疑似 Multi Page Application ができるためあまり需要はないかもしれませんが、 bun <entrypoints...>
の引数に複数のファイルを渡すことで MPA 開発もできます。
bun index.html about.html blog.html
# ➜ http://localhost:3000/
Routes:
├── / → index.html
├── /about → about.html
└── /blog → blog.html
ビルドも同様に、 entrypoints として HTML ファイルを複数渡せます。
bun build index.html about.html blog.html --outdir dist
Web サーバーから配信する (+ バックエンドAPI実装)
Bun では HTML ファイルをモジュールとしてインポート可能です。
Bun.serve()
API の static
ルートとして設定することで、バンドルした HTML ファイルを Web サーバーから配信することが出来ます。(詳しくはここ)
また、 Web 標準の fetch
メソッド(Request
を引数にして Response
を返す)で HTTP リクエストを処理することも出来ます。
Hono など、Bun と同様に Web 標準に準拠した fetch
メソッドを提供するサーバーフレームワークを組み込むことも可能です。
import index from "../index.html"; // HTML インポートが可能
import about from "../about.html";
import { Hono } from "hono";
const honoApp = new Hono();
honoApp.get("/hono", (c) => c.text("This is Hono response"));
Bun.serve({
development: true, // リクエストのたびにリビルドするなど。開発時に便利。
static: { // バンドルした静的 HTML ページを配信する
"/": index,
"/about": about,
},
async fetch(req) {
const url = new URL(req.url);
// Hono アプリでリクエストをハンドル
if (url.pathname === "/hono") {
return honoApp.fetch(req);
}
// Web 標準的の Response オブジェクトを返すことも可能
return new Response("This is default response");
},
});
console.log("Server is running on http://localhost:3000");
フロントエンドとバックエンドを同時に開発できて、一挙両得ですね。
Bun のフロントエンド開発機能で足りないもの
- ホットリロード
- プラグインの不足
- CORS やヘッダーの設定
- etc...
これらの機能はまだ work in progress らしいです。将来的には提供されると思います。
将来的には Vite などを置き換える選択肢となって、Bun 以外の依存を必要とせずフロントエンド開発ができるようになるかもしれません。
参考
Discussion
Canary build なら下記のコマンドでないと v1.2.3にアップデートできないです。
追記させていただきました。
うっかり、書き忘れてました...
ご指摘ありがとうございます!
bunfig.tomlにプラグインを指定することで
bun build index.html
でもビルドできると思います!試したけど、駄目でした...
現状、bunfig の項目でプラグイン指定できそうなのが
[serve.static].plugins
だけですね。ビルド時にプラグインを適用するには、今のところは
Bun.build()
API をスクリプトで呼び出すしかなさそうです(自分が他の方法を知らないだけかもですが)本当ですね!手元で
preload.ts
を作って読み込ませたりしたのですが動きませんねこれはissueにするべきかもしれません。教えていただきありがとうございます。