「Electron might die soon.(Electronはもうすぐ死ぬかもしれない)」
GPUIXの作者Tommy D. Rossiがこう言い放つと、すぐに衝撃的なデモが続いた。ReactとTypeScriptで書かれたチャットアプリに、5000件のメッセージを一気に詰め込む。ElectronもWebViewも使わず、インターフェース全体をGPUで描画するというデモだ。
この発言は明らかに話題作りを狙ったものだが、プロジェクト自体はコンセプト図ではない。GPUIXはすでにnpmパッケージ「@gpuix/react」と「@gpuix/native」を公開しており、本稿執筆時点のリポジトリで約1.1kのStarを獲得、最新バージョンは0.4.0である。
フロントエンド開発者にとって最も身近なReactは、今回はコンポーネントをDOMにするのではなく、Zedエディタの背後にあるGPU UIフレームワークにインターフェースを委ねる。
この道がうまくいけば、Electronにとって厄介なライバルが本当に1つ増えることになる。
■ Reactは今回、Webページをレンダリングしない
Reactはブラウザだけのものではない。
普段私たちが<div>やuseState、onClickを書いて、最終的にWebページが表示されるのは、React DOMがコンポーネントの変更をブラウザが理解できるDOM操作に変換しているからだ。React Nativeが同じコンポーネント思考でモバイルアプリを開発できるのも、レンダリング先を別のものに変えたからにほかならない。
GPUIXがやっているのはこれと同じ種類のことだ。Reactカスタムレンダラーを実装し、Reactが生成したインターフェースの変更をRust側へ送る。
コンポーネントが追加されるとReactはcreateElement、appendChildを発行し、スタイルが変わるとsetStyleを、テキストが変わるとsetTextを送る。Rust側は長期間存続する要素ツリーを保持し、GPUIが毎フレームそれをもとに一時要素を構築してレイアウトを計算し、ピクセルを画面に描く。
変化した要素だけがJavaScriptとRustの境界を越えればよく、毎回コンポーネントツリー全体をシリアライズする必要はない。
これこそGPUIXの最も賢い点だ。つまり、開発者は引き続きReactを書けるのに、アプリの実行時にはもはやブラウザ一式を背負わなくて済む。
■ Node.jsとBunは実際に何をしているのか
ReactとNode.jsは依然としてCPU上で動作する。
Reactはコンポーネントの状態、Hooks、差分計算を担当する。BunまたはNode.jsはJavaScriptの実行を担当する。Rustはインターフェースツリー、ウィンドウ、ネイティブ機能を受け持つ。実際にGPUを呼び出して描画するのはGPUIだ。
デスクトップ側はnapi-rsを通じて両者をつなぐ。プロジェクトのサンプルは主にBunで起動するが、基盤としてNode.js N-APIネイティブモジュールを提供しており、ビルド要件にはNode.js 18以上も列挙されている。
最小のアプリも、おなじみのReactの書き方のままである。
import React, { useState } from "react"
import { render } from "@gpuix/react"
function App() {
const [count, setCount] = useState(0)
return (
<div onClick={() => setCount(count + 1)}>
Count: {count}
</div>
)
}
render(<App />, {
title: "My App",
width: 800,
height: 600,
})
見た目はWebページのようだが、実行されるとそこに現れるのはネイティブウィンドウだ。HTMLファイルもブラウザDOMもBrowserWindowも存在しない。
さらにbun --hotでの開発にも対応している。TSXファイルを保存すると、Reactは元のウィンドウに再マウントされ、GPUデバイス、ネイティブウィンドウ、スクロールの物理的な挙動はすべて維持される。ただし、これは完全なReact Fast Refreshではなく、コンポーネントの状態とフォーカスはリセットされる。
■ Electronがまた「死刑宣告」される理由
Electronの強みと重荷は、同じ選択に由来する。ChromiumとNode.jsをまとめてアプリの中に組み込む、という選択だ。
この選択は開発者に完全なWebプラットフォームを与えた。HTML、CSS、Canvas、ブラウザAPI、DevTools、そして膨大なフロントエンド・コンポーネントのエコシステムを直接利用でき、macOS、Windows、Linuxで挙動を揃えるのも比較的容易だ。
その代償として、すべてのアプリがブラウザの実行環境一式を抱えることになる。プロセスが増え、インストーラは肥大化し、メモリ消費も増える。これが開発者が繰り返しElectronを批判してきた理由でもある。
GPUIXはこの中間にあるChromium層を直接取り除いた:
・Electron:React → DOM → Chromium → GPU
・GPUIX:React → Rust UIツリー → GPUI → GPU
経路が短くなったからといって、すべてのアプリが自動的に速くなるわけではない。Chromiumはもともとラスタライズ、コンポジション、アニメーションにGPUを使用しており、Electronは決して「CPUだけでUIを描いている」わけではない。GPUIXの変化は、完全なWebプラットフォームにコストを払うのをやめ、デスクトップアプリに必要な分だけのUI機能を残すことだ。
コードエディタ、ターミナル、AIチャットクライアント、Markdownリーダー、Diffビューアといったアプリにとって、この取捨選択は非常に魅力的だ。これらのアプリは高パフォーマンスなテキスト、長いリスト、スクロール、キーボード入力を必要とするが、必ずしもWebエンジン一式を必要とするわけではない。
■ 5000件のメッセージは何を証明するのか
デモのチャットUIはMarkdown、コードハイライト、テーブル、仮想化されたDiffを含みながら、スクロールしても高いフレームレートを維持している。GPUIXは<virtual-list>も提供しており、ビューポート付近の行だけを構築するため、メッセージ履歴や長いリストに適している。
アニメーションでもReactは毎フレーム関与しない。Reactは目標値を一度送るだけで、その後の補間はアニメーションが終わるまでRustが行う。これにより、N-API境界を頻繁に越える際のオーバーヘッドを減らせる。
これらの設計はいずれも、現実のデスクトップにおけるパフォーマンス問題を狙っている。
だが「5000件のメッセージ」をそのまま「Electronを性能で圧倒」と読み替えることはできない。仮想リストの目的はそもそも、全コンテンツを同時にレイアウト・描画しないことにある。プロジェクトはフレーム時間の回帰テストを用意しているが、同じデバイス、同じUI、同じデータでElectronと比較した完全なベンチマークは公表していない。
このデモは、GPUIXが複雑で滑らかなUIを作れることを示しているが、Electronが引退すべきだということはまだ証明できていない。
■ 本当の問題は性能ではなくエコシステム
GPUIXは現在わずか0.4.0で、基盤となるGPUIもpre-1.0の段階にある。Zed公式は、GPUIはまだ急速に開発が進んでおり、バージョン間で破壊的変更が頻繁に起こると明確に注意を促している。
現時点の制約も具体的だ:
・使えるのはGPUIXが実装済みの要素とスタイルのみで、完全なHTML/CSSではない。
・Ant Design、MUI、その他多数のブラウザコンポーネントをそのまま持ち込むことはできない。
・ネストしたスクロールは未対応で、複雑なインタラクションにはまだ多くの未整備部分がある。
・ブラウザ向けWebGPU版ではイベントコールバックがまだ接続されていない。
・Windows版はまだ実行時の検証待ちである。
・ソースからのビルドにはRustが必要で、macOSではMetalツールチェーンも用意しなければならない。
・プロジェクトは固定バージョンのZed/GPUIフォークに依存しており、基盤アップグレードのコストは長期的に検証されていない。
これこそ、Electronが短期的には「死なない」理由でもある。Electronの価値はレンダリング性能だけではない。クロスプラットフォームの一貫性、セキュリティモデル、デバッグツール、アクセシビリティ対応、サードパーティのコンポーネント、そして長年蓄積されたエンジニアリングの知見がある。
GPUIXは今のところ、点火したばかりのレーシングカーに似ている。スピードはものすごく見えるが、タイヤもピットクルーもサーキット全体もまだ建設中だ。
私の見立てでは、GPUIXの最も価値のある点は、また「Electronは死んだ」と叫んだことではなく、フロントエンド開発者に第三のデスクトップ路線を示したことにある。
これまでReactを書き続けたいなら、通常はChromiumかシステムのWebViewを受け入れる必要があった。今はReactを残しつつ、DOMやブラウザを必須ではなくできる。JavaScriptが開発体験を、Rustがネイティブ機能を、GPUフレームワークがUI描画を担当する。
Electronが今日死ぬことはもちろんない。
しかし次のZedやターミナル、AIクライアントが、必ずしもnew BrowserWindow()から始まるとは限らない。