検証環境:Intel MacBook Air 2018 / macOS Sonoma。7本すべて一人で開発・販売。
なぜTauriを選んだか
最初に作ったアプリはMTP経由でファイルを転送するツールだった。Electronだとビジネスロジックを一行も書く前からバイナリが150MB超え。Tauriなら10MB以下に収まる。
パフォーマンス面でも差が出る。Electronはバックエンド処理をNode.jsで書くが、TauriはRustで書く。ファイルシステムやUSBデバイスを触る処理では、この差が体感できるレベルで出る。
7本リリースした今もTauriを使い続けている。完璧だからではなく、自分のユースケースにトレードオフが合っているから。
Rustバックエンドの実際
Tauri最大の特徴はバックエンドをRustで書く点だ。Electronに慣れたWeb系エンジニアにとって、これが一番の障壁になる。
ただし慣れると強力で、コンパイル時にデータ競合・メモリ問題・並行処理のバグを検出してくれる。ファイルシステム・USBデバイス・ADBを触るアプリでは、これがランタイムエラーを実際に防いでくれた。
フロントはReact(TypeScript)、バックはRust、橋渡しはTauriのinvokeコマンド経由という構成になる。最初は違和感があるが、責務がフロント・バックできれいに分かれるため、慣れると管理しやすい。
Rustの学習コストは正直高い。所有権・借用・ライフタイムの概念はElectronのNode.jsとは別物だ。ただし、アプリの安定性に直結するので、学習投資の価値はある。また、npmエコシステムへの依存が減る分、バンドルサイズや依存関係の管理がシンプルになる副次効果もある。
実際にハマったポイント
権限設定(capabilities)でつまずきやすい
Tauri v2からpermissions/capabilitiesの仕組みが大きく変わった。v1の記事を参考にすると情報が古くて沼にはまる。
解決策はシンプルで、tauri.conf.jsonのcapabilitiesに必要な権限を明示的に列挙するだけだ。ファイルアクセスが通らない場合はまずここを疑う。この理解に2日かかった。
macOSコード署名・公証(notarization)が必須
App Store外で配布する場合、以下がすべて必要になる。
- Apple Developer Program(年間$99)への登録
- Developer ID Application証明書の取得
- xcrun notarytoolによる公証
- DMGへのstaple
一つでも抜けると、ユーザー環境で「"xxx"は壊れているため開けません」が表示される。
今はtauri build → xcrun notarytool submit → xcrun stapler stapleの流れを毎回同じ手順で回している。
グローバルショートカットはsetup()フック内で登録する
Tauri v2でグローバルキーボードショートカットを実装する場合、登録タイミングが重要になる。setup()フック内で登録するのが正しい。タイミングを誤ると他アプリのショートカットを奪う・逆に動作しないといった問題が起きる。
メニューバーアプリは通常ウィンドウアプリと設定が異なる
tauri.conf.jsonのactivation_policyをAccessoryに設定しないと、メニューバーアプリなのにDockにアイコンが出続ける。ドキュメントに記載はあるが見落としやすい。
配布・販売まわりの現実
Tauriの問題ではないが、macOSアプリをApp Store外で販売する場合、開発とは別のコストがかかる。
Universal Binary(Intel + Apple Silicon両対応)のDMGビルドは毎回時間がかかる。ライセンス認証はApp Store外のため自前実装が必要で、Cloudflare Workersで管理している。販売プラットフォームはGumroadかLemonSqueezyが現実的な選択肢になる。
開発そのものより、この配布・販売まわりで詰まる時間の方が最初は多かった。
まとめ
Tauriは以下の条件が揃う場合、個人開発者がmacOSアプリを作る選択肢として十分に実用的だ。
- Rustの学習コストを受け入れられること
- macOSの署名・公証フローを一度きちんと理解できること
- Electronのエコシステム(npmパッケージ群)への依存が少ないこと
逆に、既存のNode.js資産やnpmエコシステムをそのまま活かしたい場合はElectronの方が向いているケースもある。
8年前のIntel MacBook Airでも開発・販売まで問題なく持っていける。少なくとも7本はそうだった。