6月25日、Denoが「Deno 2.9」と題した記事を公開した。Deno 2.9では、ElectronやTauriを使わずにWebスタックだけでネイティブデスクトップアプリを構築できる実験的機能「deno desktop」が追加された。加えて、v2.8比で起動速度約2倍・メモリ使用量約3分の1という大幅なパフォーマンス改善と、npm/pnpm/yarn/Bunからの移行サポートの強化が盛り込まれている。
ElectronはChromiumをまるごとバンドルするため、Hello World級のアプリでも数百MBのバイナリと高いメモリ消費が避けられない。代替として登場したTauriはOSのWebViewを利用してバイナリサイズを抑えるが、Rustの学習コストが壁になるケースもある。deno desktop はDenoランタイムをそのまま使い、同様にOSのWebViewを活用する設計で、TypeScript/JavaScriptだけで完結するのが特徴だ。Denoはすでにサーバーサイドとフロントエンドのツールチェーンを統合する方向を進めており、deno desktop はその延長線上でデスクトップ領域へも一気通貫のDX(開発者体験)を持ち込む試みといえる。
目玉機能:deno desktop でElectron不要のデスクトップアプリ
deno desktop は新しいサブコマンドとして追加された。最小限の実装はこれだけだ:
// main.ts
Deno.serve(() =>
new Response(
"<!DOCTYPE html><h1>Hello from Deno desktop 👋</h1>",
{ headers: { "content-type": "text/html" } },
)
);
Deno.serve() をデスクトップエントリポイントとして呼ぶと、WebViewが開くポートに自動でバインドされる。ポートの手動設定は不要で、出力は単一の実行バイナリになる。
フレームワーク検出機能も備わっており、deno desktop . を実行するだけで、カレントディレクトリのWebフレームワーク(Next.js、Astro、Fresh、Remix、Nuxt、SvelteKit、SolidStart、TanStack Start、Vite SSR)を自動検出してビルドする。既存のWebアプリをデスクトップアプリに転換するコストが極めて低い。
ネイティブAPIも充実
Deno.BrowserWindow でウィンドウのサイズ・位置・メニューをプログラム制御できる。WebView側のJavaScriptとDenoのロジックをブリッジする window.bind() も用意されている。macOSの Deno.Dock、システムトレイ用の Deno.Tray も利用可能だ。
// tray.ts
const tray = new Deno.Tray();
tray.setIcon(iconBytes);
const panel = tray.attachPanel({ url: "https://localhost:8000/panel" });
panel.window.bind("doThing", async () => {});
ブラウザエンジンは2択
--backend オプションでエンジンを切り替えられる:
- **
webview**(デフォルト): OSのビルトインエンジン(Windows=WebView2、macOS/Linux=WebKit)を使用。追加バンドルなしでバイナリが小さく起動が速い cef: Chromiumをバンドルし、全プラットフォームで同一レンダリングを保証。ただし数十MB追加される
クロスコンパイルも一発
$ deno desktop --output MyApp.dmg main.ts
$ deno desktop --target x86_64-pc-windows-msvc main.ts
$ deno desktop --all-targets main.ts
--all-targets を使えば、1台のLinux CIランナーからWindows・macOS・Linux向けバイナリをまとめて生成できる。対応フォーマットはmacOSが .app/.dmg、Windowsが .exe/.msi、Linuxが .AppImage/.deb/.rpm だ。
なお、deno desktop は2.9時点では実験的機能であり、一部のプラットフォーム機能はまだ実装中とされている。実際の動作例として、deno desktop で構築されたメモアプリ denidian が公開されており、実用的な使用感を確認できる。

パフォーマンス改善がv2.8比で実用レベルで大きい
起動速度とメモリ使用量の改善が特に顕著だ。コールドスタートは34msから17msへ約2倍高速化し、メモリ(RSS)はワークロードによらず約62MBに安定した。v2.8ではワークロードに応じてRSSが94MB〜197MBと大きく変動していたのと比べると、同一マシンで動かせる Deno.serve インスタンス数が大幅に増える計算になる。
以下はDeno 2.8との比較で、専用のx86_64 Linuxマシン上での計測値だ:
| 指標 | v2.8 | v2.9 | 改善率 |
|---|---|---|---|
| コールドスタート | 34ms | 17ms | 約2倍高速 |
Deno.serve リアルワールド |
56.8k req/s | 72.4k req/s | 約1.27倍 |
Deno.serve プレーンテキスト |
77.0k req/s | 85.6k req/s | 約1.11倍 |
Deno.serve 1MiBボディ |
1,617 req/s | 1,907 req/s | 約1.18倍 |
| RSS(リアルワールド) | 142MB | 64MB | 約2.2倍削減 |
| RSS(1MiBボディ) | 197MB | 63MB | 約3.1倍削減 |
コールドスタートの高速化には、node: グローバルのスナップショットへの遅延ロード、V8コードキャッシュの導入、スナップショットの最小化などが寄与している。HTTPスループット改善はDeno独自のHTTP/1.1サービングパスの新実装が主な要因だ。crypto.subtle と console/Deno.inspect のホットパスもJavaScriptからRustへ移植された。
npm/pnpm/yarn/Bun からの移行が容易に
既存のNodeプロジェクトをDenoに移行する際の最大の障壁の一つは、依存関係の固定バージョン情報の引き継ぎだった。2.9ではこれが解決された。
deno.lock が存在しない状態で deno install を実行すると、既存の package-lock.json・pnpm-lock.yaml・yarn.lock・bun.lock から直接 deno.lock を生成する。再解決は行われず、以前使っていたバージョンがそのまま引き継がれる。
$ deno install
Seeded deno.lock from package-lock.json
pnpmワークスペース(pnpm-workspace.yaml)も自動検出して package.json または deno.json に移行される。Next.jsのTurbopackワーカーのように node バイナリに直接依存するツール向けには、node コマンドのシムをPATHに追加してDenoに転送する仕組みも追加された。
その他の注目変更点
CSSモジュールインポート(--unstable-raw-imports フラグが必要):Web標準のCSS Module Scripts仕様に準拠した形でCSSファイルを直接インポートできる。インポート結果は CSSStyleSheet インスタンスになり、バンドラーなしでフロントエンドコードのテストが容易になる。
import sheet from "./styles.css" with { type: "css" };
document.adoptedStyleSheets = [sheet];
deno link / deno unlink:ローカルパッケージのリンクをCLIで管理できる npm link 相当の機能だ。deno list:npm ls / pnpm list 相当の新サブコマンドで、プロジェクトの依存関係と解決済みバージョンを一覧表示する。Node.js 26互換性:Node.js 26で追加されたAPIへの対応も含まれる。
デスクトップアプリ開発からサーバーサイド、フロントエンドツールチェーンまで、Denoが「JavaScript/TypeScriptの実行環境」から「開発プラットフォーム」へと進化しようとしている姿勢がこのリリースからは伝わってくる。
詳細はDeno 2.9を参照していただきたい。