Bun.server の変更を検知して Hot Reload するためのパッケージを作った
Bun には元々 Watch mode という、実行ファイルの変更を検知して再読み込む機構が二種類用意されている。
しかし、これはあくまでプロセスとして再実行もしくは再読み込みをしてくれる機構であるため、例えば React アプリケーション的なAPIサーバーでは、変更を反映するためにはブラウザを再リロードする必要がある。
Vite などのエコシステムを使用することで HMR (Hot Module Replacement) が実現できる。先ほどの例でもファイル変更をブラウザへと自動的に反映してくれる具合だ。
最近、Bun を使った Web アプリケーション開発についてあれこれ調べていて興味も沸いたこともあり、「Vite を構築するまではないがブラウザにも自動的に反映してほしい」という個人的な課題を解決するためのパッケージを作った
`bun run --hot src/index.ts` と実行したBun API サーバーが変更検知され再読み込み (もしくはプロセス再起動) された場合、ブラウザにも通知してタブをリロードする `location.reload()` という機能になる。
全く同じ課題を解決する先行パッケージはすでにあったが、参考にさせてもらい、習作としてイチから構築した。パッケージ側で WebSocket を利用するため、パッケージ利用側で WebSocket を利用する場合との兼ね合いを整えたり、ブラウザに埋め込むJSファイルをできる限り関数として扱うなど、細かい部分でやりたいようになった。
また、実行したサーバー以外にも、クライアントコンポーネントなどの変更を監視・ビルドできるようにしているが、ビルドされたファイルの配信は自分でやる必要がある (dist ディレクトリの配信、script タグの埋め込みなど)。あくまで変更を検知してブラウザを更新するための薄いパッケージだ。
補足情報
パッケージで提供している機能は、ブラウザへの反映で location.reload() しているため HMR ではない (ログの接頭辞に `HMR` と表記してしまったが)
また、近々 Vite の import.meta.hot をサポートする予定があるため、より良い開発体験が得られるようになりそうだ (現状でも Vite は動くが)
感想
作りながら改めて思ったが、Vite のエコシステムは本当に良くできている。使えるならそちらに乗っかった方が良い。
今回作ったのはシンプルな変更通知やビルド機能だけだが、別の言い方をすると未熟であるということだ。Bun によって最低限のものはできたと考えているが、HMR (つまり location.reload() ではない画面反映) や react-refresh など、開発体験を高める要素は多岐に渡り、複雑だ。
ただ、とても良い勉強になった。