Bun.Imageで画像処理パイプラインが過去のものに

BBetter Stack
Computing/SoftwareInternet Technology

Transcript

00:00:00今回は Bun 1.3.14 で追加された内蔵画像処理 API「Bun Image」をご紹介します。ネイティブの依存関係なしで画像の
00:00:06リサイズ、切り抜き、異なるフォーマット間での変換を行うことができ、
00:00:10処理のすべてがメインスレッド外で実行されるため、処理中もサーバーがブロックされません。
00:00:14しかし、Bun はすでにランタイムであり、パッケージマネージャーであり、バンドラーであり、テストランナーでもあります。
00:00:19そこに画像処理まで追加されるとは、やりすぎなのでしょうか?それとも、Bun の今後の方向性を示す
00:00:24大きなメッセージなのでしょうか?チャンネル登録をして確かめてみましょう。
00:00:30JavaScript でサーバー上の画像を処理したことがある方なら、知らず知らずのうちに「Sharp」という
00:00:35ライブラリを使っていたかもしれません。npm で週に 5,500 万回以上ダウンロードされており、
00:00:41Next.js の内部でも画像最適化に使われています。しかし Sharp は「libvips」というネイティブバイナリに依存しているため、
00:00:47インストールするたびにプラットフォームに合ったビルドを取得する必要があります。Docker のビルドや
00:00:51CI パイプラインがこれが原因で失敗した経験がある方なら、その面倒臭さがよく分かるはずです。そこで Bun は
00:00:57ランタイム自体に画像処理機能を組み込むことにしました。これがほとんどのベンチマークで Sharp よりも高速です。
00:01:02メタデータの読み込みは最大 70 倍速く、リサイズも約 30%高速です。多くの開発者は、
00:01:08なぜ Bun がこれを追加したのか戸惑っていますが、私にはその目指すところが少し見えている気がします。
00:01:13それについては後でお話しするとして、まずは Bun Image API の使い方をいくつかのデモを通して見ていきましょう。
00:01:17今回は、巨大な画像を使用している私のブログ(静的な Waku サイト)で試してみたいと思います。
00:01:22手始めに、私の顔写真であるプロフィール画像を最適化するシンプルなスクリプトを見てみましょう。
00:01:27なんと、ファイルサイズを 99%も削減することができました。驚異的な数字です。
00:01:33その仕組みを見てみましょう。まず画像を取得します。ここでは `Bun.image` を使用していますが、
00:01:37`Bun.file` と image 関数を組み合わせることも可能です。次に、サイズを縮小するために画像をリサイズします。幅を 800 ピクセルに指定し、
00:01:43高さはアスペクト比に基づいて自動的に計算されます。もちろん、必要であれば
00:01:47ここで高さを指定することもできます。そして、品質を下げた WebP 形式を出力フォーマットとして指定します。もちろん
00:01:52他の出力フォーマットもサポートされています。最後に、新しい画像をファイルに出力します。
00:01:56これは Promise を返すため、`await` キーワードが必要です。これだけでいかに簡単に実装できるかが分かります。
00:02:01実際、ここにあるコードの一部は不要なので、削除してさらにシンプルにすることも可能です。
00:02:06また、リサイズフィルターを設定してリサンプリングカーネルを変更し、画像サイズをさらに削減することもできます。
00:02:10画像の回転や反転も可能で、これは非常に便利です。明るさや彩度を変更することさえでき、
00:02:15ユニークな見た目の画像を作ることもできます。しかし、低速なネットワーク環境において非常に賢い方法があります。
00:02:19それは、placeholder 関数を使って、メイン画像の読み込み中にぼかした画像を自動的に表示することです。
00:02:23そのために、ブログ画像が格納されているディレクトリ内で、指定した拡張子を持つすべてのファイルをループ処理する
00:02:29コードを用意しています。各画像はクロップされずに縮小され、アップスケールされることなくリサイズされます。
00:02:34そして画像ごとにプレースホルダーを作成します。これにより ThumbHash が生成され、
00:02:39任意の画像を 28 バイトのハッシュにエンコードするため、ぼかしプレースホルダーとして最適です。
00:02:45このハッシュはプレースホルダーオブジェクトに追加され、ファイルに書き込まれます。
00:02:49出力結果は次のようになります。ここで、プレースホルダーに別の小さな WebP 画像ではなく
00:02:53Base64 画像を使用する理由は、それを取得するためのネットワークリクエストを発生させないためです。
00:02:58したがって、すべてのプレースホルダーをインポートし、メイン画像の読み込みを待つ間の CSS の背景画像として
00:03:02設定すれば、ブログ上のすべての画像でこの機能が動作します。
00:03:07もし MDX ファイル内の単一の画像に対して行いたい場合は、Base64 コードを手動で追加するだけで、
00:03:11同じように機能します。なお、JPEG 画像の場合は `progressive` を `true` に設定することでも
00:03:16同様の動作を実現できます。もちろん、Bun Image がサポートしている機能はこれだけにとどまりません。
00:03:20S3 互換バケットからの画像取得や、バケットへの画像保存、画像パイプラインをレスポンスボディとして直接利用すること、
00:03:24特定の OS がサポートしていない場合のフォールバックフォーマットの設定なども可能です。
00:03:28では、これを使う価値はあるでしょうか?すでに Bun を使っているなら、間違いなく採用すべきです。
00:03:33しかし Node.js を使っている場合、Sharp は非常に優れていて実績もあるため、
00:03:37画像処理のためだけにまったく異なるランタイムに変更する必要はないでしょう。
00:03:41Bun がこの機能を追加した背景には、さらに大きな理由があると言ったのを覚えていますか?
00:03:45ここ 1 年間の Bun の動向を見てみると、内蔵 SQLite、S3、Postgres、そして今回の画像処理と、
00:03:49認証とメール機能を除けば、フルスタックアプリに必要なものがほぼすべて揃っています。
00:03:54これにより、ある疑問が湧いてきます。Bun は JavaScript 版の Laravel や Rails を
00:03:59ランタイムレベルで構築しようとしているのではないでしょうか?もしそうだとすれば、
00:04:04次に手掛けるのは認証機能のはずです。もしそうなら、この動画で一番最初に聞いたことを思い出してください。
00:04:11しかし残念ながら、現在の Bun を語る上で、Zig から Rust への大規模な書き直しに触れないわけにはいきません。
00:04:15うまくいけば次期バージョンで登場する予定です。すべてが順調に進むことを祈りましょう。
00:04:20Zig といえば、Vercel の言語である「Zero」についてもっと知りたいですか?Zig に似ていますが Zig ではなく、
00:04:25AI エージェント向けに構築されたその言語については、James のこちらの動画をチェックしてみてください。
00:04:29Zig ではなく、AI エージェント向けに構築されたその言語については、James のこちらの動画をチェックしてみてください。

Key Takeaway

Bun 1.3.14で導入された内蔵画像処理API「Bun Image」により、外部のネイティブバイナリ依存なしで高速な画像リサイズやプレースホルダー生成が可能になる。

Highlights

  • Bun 1.3.14で追加された内蔵画像処理API「Bun Image」は、ネイティブの依存関係なしで画像の処理を実行する。

  • メタデータの読み込みは最大70倍速く、リサイズ処理は約30%高速である。

  • プロフィール画像の最適化においてファイルサイズを99%削減することに成功した。

  • プレースホルダーには任意の画像を28バイトのハッシュにエンコードするThumbHashを使用し、Base64画像として読み込み中の背景に設定する。

Timeline

Bun Imageの概要と導入背景

  • Bun 1.3.14で内蔵画像処理API「Bun Image」が追加された。
  • 処理のすべてがメインスレッド外で実行され、サーバーがブロックされない。
  • 従来のSharpライブラリが抱えるネイティブバイナリ依存の課題を解消する。

画像のリサイズ、切り抜き、フォーマット変換をネイティブ依存なしで行える。多くの現場で使用されるSharpはlibvipsへの依存によりDockerやCIパイプラインでビルドエラーを引き起こす原因となっていた。Bunはこの問題を解決するため、ランタイム自体に画像処理機能を組み込み、メタデータ読み込みで最大70倍、リサイズで約30%の高速化を実現している。

Bun Imageの実装と最適化手法

  • プロフィール画像の最適化でファイルサイズを99%削減した。
  • プレースホルダーにThumbHashを用いた28バイトのハッシュを生成し、ネットワークリクエストを発生させない。
  • リサイズフィルターや明るさ、彩度の変更など多彩な調整が可能である。

Bun.imageとBun.fileを組み合わせて画像を縮小し、出力フォーマットや品質を指定する。低速なネットワーク環境向けにプレースホルダー関数を活用し、メイン画像の読み込み中にぼかした画像を自動表示する仕組みを構築できる。Base64形式のプレースホルダーをCSSの背景画像として設定することで、追加のネットワークリクエストを防ぎつつ滑らかな読み込み体験を実現する。

Bunの今後の展望

  • S3互換バケットからの画像取得やフォールバックフォーマットの設定もサポートされている。
  • 内蔵SQLite、S3、Postgres、画像処理の追加によりフルスタックアプリに必要な機能が揃いつつある。
  • 今後のアップデートとしてZigからRustへの大規模な書き直しが予定されている。

すでにBunを使用している環境では採用の価値が高いが、Node.jsとSharpの既存環境を無理に変更する必要はない。認証やメール機能を除けばフルスタックアプリの要件を満たしつつあり、JavaScript版のLaravelやRailsをランタイムレベルで構築する方向性が示唆されている。

Community Posts

View all posts