6 つのプラットフォームすべてで完全な機能パリティ
Perryのネイティブ UIシステムの最初のバージョンを出荷した時、「クロスプラットフォーム」とは macOSがうまく動き、他の5つのプラットフォームはスタブという意味でした。v0.2.162の今日、 それはもう当てはまりません。6つのプラットフォームすべて — macOS、iOS、iPadOS、Android、Linux、Windows — が 完全な機能パリティを共有しています。同じTypeScriptコードがすべてのターゲットでネイティブウィジェットにコンパイルされます。
この記事では、v0.2.152からv0.2.164の間に出荷したものを紹介します:Canvasウィジェット、 完全なNSTableView実装、20以上のUIウィジェット、 perry/system モジュール、マルチウィンドウサポート、 システム通知、キーチェーンアクセス、自動バイナリサイズ削減、そしてコンパイル時プラグインシステム。 多くのことがありました。
ウィジェットスプリント:20以上のネイティブUIコンポーネント
最大の進歩はv0.2.155で、全プラットフォームにわたって20以上のUIウィジェットが追加されました。 PerryのTypeScript UI APIは、実際のアプリを出荷するために必要なコンポーネントをカバーしています:
- レイアウト — VStack、HStack、ZStack、LazyVStack、ScrollView、SplitView
- 入力 — Button、TextField、TextEditor、Checkbox、Toggle、Slider、Picker
- 表示 — Text、Label、Image、ProgressView、Divider、Spacer
- データ — List、Table(NSTableView / GTK4 TreeView / Win32 ListView)
- オーバーレイ — Alert、Sheet、Popover、Toolbar、NavigationBar
- 描画 — Canvas(2D描画API、プラットフォームごとにハードウェアアクセラレーション)
これらはカスタムレンダラーのラッパーではありません。各ウィジェットはプラットフォーム固有の ネイティブコンポーネントにコンパイルされます:macOSでは NSButton、 iOSでは UIButton、 Linuxでは GtkButton、 AndroidではJNI経由で android.widget.Button、 Windowsでは CreateWindowEx。 OSがそれらを描画し、テーマを適用し、アクセシビリティを処理します — Perryは TypeScript APIを接続するだけです。
Canvas:TypeScriptからの2D描画
技術的に最も興味深い追加の1つがCanvasウィジェット(v0.2.152)です。TypeScriptから直接 馴染みのある2D描画API — ベジェ曲線、塗りつぶし、ストローク、画像ブリッティング — を公開し、 プラットフォームのアクセラレーテッド2Dバックエンドにコンパイルされます: macOS/iOSではCore Graphics、LinuxではCairo、WindowsではDirect2D、AndroidではSkia。
import { Canvas, Color } from 'perry/ui';
// Compiles to Core Graphics on macOS, Cairo on Linux, etc.
const canvas = new Canvas({ width: 400, height: 300 });
canvas.onDraw((ctx) => {
ctx.fillStyle = Color.amber;
ctx.fillRect(10, 10, 100, 60);
ctx.strokeStyle = Color.blue;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(200, 150, 80, 0, Math.PI * 2);
ctx.stroke();
});
Tableウィジェット:NSTableViewがTypeScriptに
v0.2.163でTableウィジェットが追加されました — ライブラリ内で最も複雑なコンポーネントです。macOSでは 完全なdelegate/data sourceの接続を持つ NSTableView に対応します。 LinuxではGTK4の GtkTreeView を使用します。Windowsでは Win32の ListView コントロール。AndroidではJNIを通じて RecyclerView にバインドされます。
TypeScript APIは宣言的です:カラムを定義し、データソースを提供すれば、Perryがコンパイル時に プラットフォーム固有の接続を処理します。カラムソート、選択ハンドリング、行の高さ カスタマイズがすべてそのまま動作します。
import { Table, Column } from 'perry/ui';
const table = new Table({
columns: [
new Column({ title: "Name", key: "name", width: 200 }),
new Column({ title: "Size", key: "size", width: 80 }),
],
rows: files, // TypeScript array of objects
onSelect: (row) => console.log(row.name),
});
perry/system モジュール
v0.2.155では perry/system も導入されました — ランタイムなしで プラットフォームのシステムAPIを公開するTypeScriptモジュールです:ファイルダイアログ、 保存ダイアログ、アラート、シート、キーチェーンアクセス、システム通知、マルチウィンドウ管理。
system.showOpenDialog()— ネイティブファイルピッカー(NSOpenPanel / GTK FileChooser / Win32 OPENFILENAME)system.showSaveDialog()— ネイティブ保存ダイアログsystem.showAlert()— ネイティブアラートパネルsystem.notify()— OS通知(UserNotifications / libnotify / WinRT)system.keychain.get/set()— Keychain Services / Secret Service / Windows Credential Storesystem.openWindow()— マルチウィンドウ管理
これらはすべてネイティブプラットフォームAPIを直接呼び出します — Electron IPCもWeb Viewブリッジもありません。 PerryはTypeScriptの呼び出しサイトをプラットフォームSDKへの直接的なネイティブ関数呼び出しにコンパイルします。
6プラットフォーム機能パリティ:v0.2.162
v0.2.162のマイルストーンはギャップを埋めることでした。このリリース前は、macOSが最も充実した 機能セットを持ち、iOSはほぼ揃っていましたが、Linux/Windows/Androidは遅れていました。v0.2.162は 6つのプラットフォームすべてを同じレベルに引き上げました:
- macOS — AppKit、完全なウィジェットセット、Keychain、通知、マルチウィンドウ、ツールバー
- iOS / iPadOS — UIKit、macOSとの完全なウィジェットパリティ、シーンライフサイクル
- Android — JNIブリッジ、Android Views経由の全ウィジェット、NDKクロスコンパイル
- Linux — GTK4、Tableを含む完全なウィジェットセット、ファイルダイアログ、libsecretキーチェーン
- Windows — Win32、全ウィジェット、Windows Credential Store、WinRT通知
これは「1つのコードベース、6つのプラットフォーム」を願望ではなく現実にするマイルストーンです。 同じTypeScriptファイルが、一般的なユースケースに対してプラットフォーム固有の コードパスを必要とせず、6つすべてのターゲットでネイティブアプリにコンパイルされます。
自動バイナリサイズ削減
v0.2.153では自動バイナリサイズ削減が出荷されました — コンパイラは使用されていないコードパスを 積極的にデッドストリップし、到達不能なstdlib関数を排除し、リンク時にシンボル定義を 重複排除するようになりました。以前は約4 MBにコンパイルされていた典型的なCLIツールが、 ソースを変更することなく2 MB以下になります。
これは実際のデプロイメントにとって重要です。バイナリがデプロイメントの単位である場合 — サーバーにコピーしたり、 単一ファイルとして配布したり、コンテナに埋め込んだり — サイズは転送時間とストレージコストに 直接影響します。バイナリサイズを無料で半分にすることは意味のある改善です。
コンパイル時プラグインシステム
v0.2.152ではPerryのプラグインシステムが導入されました — そしてそれはTypeScriptエコシステムの 他のあらゆるプラグインシステムとはアーキテクチャ的に異なります。ランタイムプラグインローディングなし、 IPCなし、動的な require() なし。プラグインはPerryがビルド時に 解決しコンパイルするTypeScriptモジュールです。
結果:プラグインのランタイムオーバーヘッドは完全にゼロです。アプリケーションコードと同じバイナリにコンパイルされ、 プラグインコードとホストコード間は直接関数呼び出しです。プラグインを使わなければ、 バイナリにまったく含まれません。使えば、他のモジュールと同様にインライン化されます。
この背景にある哲学については プラグインシステムはパフォーマンスの税金で書きました。要約すると:ランタイムプラグインアーキテクチャはパフォーマンスと拡張性をトレードオフします。 ビルド時コンポジションは両方を実現します。
言語の改善
UIスプリントは単独で起こったわけではありません — コンパイラ自体も継続的により高機能になりました。 これらのリリースを通じて:
- クラス式 —
const Foo = class extends Bar {}が正しくコンパイルされるようになりました - ジェネレータ変換 —
function*とyieldがネイティブステートマシンにコンパイルされます - クラスフィールドとしてのMap/Set —
private items = new Map()がコード生成で動作します - FFIパラメータ型強制 — ネイティブライブラリ呼び出しが型強制を自動的に処理します
- バウンドメソッド参照 —
this.method参照がネイティブモジュール(fs、os、path)で動作します string.match()— 完全サポートされるようになりましたpath.isAbsolute()、マルチ引数path.join()、path.resolve()- Webターゲット — Perryはハイブリッドデプロイメント用のWeb互換出力にコンパイルできるようになりました
次のステップ
6プラットフォームのUIパリティが出荷されたので、次のフェーズは広さよりも深さです。現在取り組んでいるのは:
- 完全なRegExpサポート(
regex.test()、string.matchAll()) - ウィジェットシステムでのドラッグアンドドロップ、カスタムコンテキストメニュー、アクセシビリティラベル
- Perry診断とコンパイル・オン・セーブのためのVS Code拡張機能
- パッケージマネージャー統合 — Perryネイティブパッケージのインストールとコンパイルを1コマンドで
- ブラウザデプロイメント用のWASMコンパイルターゲット
Workerスレッドによるマルチスレッディング
フォローしたい方は、 Perryリポジトリがオープンです。 ショーケース で既に構築されているものを確認するか、 ロードマップ で全体像をご覧ください。