Sik.limited Logo

Electron代替フレームワーク比較: Tauri・Wails・Neutralinojsを選ぶ基準

Electronからの移行または新規デスクトップアプリのために、Tauri、Wails、Neutralinojsのランタイム、権限、WebView、運用コストを比較します。

Sik ·

まず、捨てたいコストに名前を付ける

Electron代替を探す理由を「アプリを軽くしたい」だけにすると、移行後に別の重さを見つけます。インストーラー、メモリ、ビルド時間、Chromium更新、OS別UI差、Node.jsの権限、IPCのレビュー、既存プラグイン、チームの言語能力は別々の費用です。先に「どの費用をどの利用者のために下げたいか」を記述します。

たとえば、配布物を小さくしたいのか、Chromiumを同梱して更新する運用を減らしたいのか、rendererとOS APIの境界を厳しくしたいのか、既存Goサービスをローカル機能へ持ち込みたいのか。目的が異なれば、Tauri、Wails、Neutralinojsの適切な評価軸も変わります。

現在の痛み最初に測るもの見落としやすい費用
配布物が大きいOS別インストーラー、ダウンロード、初回起動WebView前提、サポート対象OS
メモリが気になる中核行動中のCPU・メモリ・起動後の安定性画像、一覧、IPC、バックグラウンド処理
IPCが広いrendererが到達可能な能力一覧移行後の新しいブリッジ設計
ビルドが遅いCI時間、署名、失敗率SDK・Rust・Goツールチェーン
UIを統一したいOS別の実機QA結果システムWebViewの差

三つのフレームワークは同じWebViewアプリではない

三つともWeb技術のUIをデスクトップへ持ち込みますが、ネイティブコードとの接点と安全に保つ方法が異なります。

観点TauriWailsNeutralinojs
ネイティブ側Rust commandとプラグインGoのメソッド・サービスJavaScript APIと拡張
画面システムWebViewシステムWebViewシステムWebView
典型的な強みcapability・permission・scopeによる明示的境界Goで書いた既存ドメイン処理との接続小さい単機能ツールの単純な構成
主な確認点OS別WebView、Rust、権限ファイルGo境界、バインディング、OS別描画必要API、更新、製品規模の上限

この表は優劣ではなく、どの境界をチームが保守できるかを示します。どれでも、画面に任意のローカル権限を渡さず、端末機能を小さいAPIで囲う設計は必要です。

Tauri: 権限モデルまで製品コードとして扱いたいとき

TauriはWebフロントエンドとRustコアを結び、OSのWebViewを使います。価値は単純な軽量化だけでなく、windowごとのcapability、permission、scopeにより、画面が何へ到達できるかを設定とコードで明示できることです。

#[tauri::command]
fn export_note(body: String) -> Result<(), String> {
    if body.len() > 1_000_000 { return Err("Note is too large".into()); }
    // 保存先・権限・入力検証はここでさらに限定する
    Ok(())
}
{
  "identifier": "editor",
  "windows": ["main"],
  "permissions": ["core:default", "dialog:allow-save"]
}

Rustを新たに導入する費用、Windows・macOS・LinuxのWebView差、プラグインのpermission識別子を版ごとに確認する運用は必要です。Tauriを選ぶなら「バンドルが小さいから」ではなく、ローカル能力を狭く監査したいという目的を満たせるかで判断します。

Wails: Goのサービスモデルをデスクトップへ持ち込みたいとき

WailsはGoバックエンドとWebフロントエンドを結びます。既にGoでドメインロジック、同期、ローカルDB、CLI、サービス層を持つチームなら、言語境界を増やさずにデスクトップ化できることがあります。フロントエンドから呼ぶGoの公開メソッドは、HTTP APIと同様に入力・出力・エラーを契約として扱います。

// app.go
type App struct{}
type ExportInput struct { Name string; Body string }

func (a *App) ExportMarkdown(input ExportInput) error {
  if len(input.Body) > 1_000_000 { return errors.New("export is too large") }
  if !strings.HasSuffix(input.Name, ".md") { return errors.New("only .md is allowed") }
  return nil
}

Goのメソッドを広く公開すると、Electronで任意IPCを公開するのと同じ問題を別名で作ります。UIの用途ごとに小さなサービスを設け、ファイルパス、サイズ、状態をGo側で検証します。Go採用の利点が既存資産ではなく単なる「Rustを避けたい」だけなら、長期の保守責任まで比較してください。

Neutralinojs: 小さく単純なツールの境界を明確にしたいとき

Neutralinojsは小さなデスクトップユーティリティを考える際に候補になります。メニューバー補助、ローカルデータの表示、単発の変換ツールのように、端末機能が限られ、長期的に大規模な統合を必要としない場合に相性を評価できます。

小さいランタイムは「機能が自動的に安全」とは意味しません。どのnative APIをUIへ渡すか、ユーザー入力をどこで検証するか、更新、署名、クラッシュ報告をどう運用するかは製品で決める必要があります。まず必要なOS APIをリスト化し、PoCでOS別のファイル、ダイアログ、通知、描画を通します。

// 例: UIから任意のシェル操作を許さず、用途を限定した関数にする
export async function exportText(name: string, body: string) {
  if (!name.endsWith('.txt')) throw new Error('Text files only');
  if (body.length > 1_000_000) throw new Error('File too large');
  // 実際のnative APIは導入したバージョンの文書に合わせる
}

システムWebViewはコストを消すのでなく、場所を変える

Chromiumを同梱しない選択は配布物を小さくできることがありますが、描画エンジンの更新をOSや環境に委ねることでもあります。フォント、入力、ドラッグ&ドロップ、アクセシビリティ、CSS機能、動画、エディタ、認証画面を、対象OSの実機で試します。ChromeのスクリーンショットだけでWebView QAを済ませません。

検証場面記録すること
初回起動OS、WebView版、起動までの時間、失敗時メッセージ
編集・IME日本語入力、貼付け、ショートカット、フォーカス移動
ファイルダイアログ取消、権限なし、外部ボリューム、長いパス
認証リダイレクト、外部ブラウザ、セッション復帰
更新署名、失敗時の復旧、既存データの移行

移行はrendererから始めない

Electronのrendererを先にコピーすると、古いpreload API、IPC名、Node前提をそのまま新しいフレームワークへ持ち込む危険があります。最初にやるべきは、現在のアプリが持つ能力を列挙し、画面、preload、main、外部サーバーのどこにあるかを可視化することです。

現在の能力
  ファイルを選ぶ ── dialog
  下書きを保存 ── preload → IPC → main → fs
  更新を確認 ──── main → 更新サービス
  分析を送る ──── renderer → HTTPS API

次に、各能力の入力、戻り値、権限、失敗時UIを一つずつ書きます。新フレームワークではそれをRust command、Goメソッド、または限定native APIへ写します。UIコンポーネントの移植は最後に近い仕事です。UIは古い能力を呼ばないアダプターを通すようにしておけば、移行中もブラウザ版とテスト版を保てます。

export interface FileExporter {
  chooseDestination(): Promise<string | null>;
  writeMarkdown(path: string, body: string): Promise<void>;
}

4週間の意思決定PoCに必要な最小範囲

PoCの目的はフレームワークの見た目を比べることではなく、戻りにくい前提を検証することです。

  1. 1週目: 対象OS、署名、起動、WebView上の中核画面を確認する。
  2. 2週目: 最も危険なローカル機能(ファイル、資格情報、DBなど)を最小権限で通す。
  3. 3週目: 認証、オフライン、データ移行、エラー表示を実機で通す。
  4. 4週目: CI、パッケージ、更新、アンインストール/再インストール、運用手順を記録する。

成果は「成功したデモ」ではなく、OS、SDK、署名、権限、失敗ケース、未解決コストの一覧です。

選択のための短い決定ツリー

既存Electronで解決できない具体的なコストがあるか?
  └─ ない → Electronの保守・セキュリティ境界をまず改善
  └─ ある → 既存Go資産が中心か?
      └─ はい → WailsのPoC
      └─ いいえ → 権限を宣言的に狭め、Rust境界を置きたいか?
          └─ はい → TauriのPoC
          └─ いいえ → 機能が小さい単機能ツールか?
              └─ はい → Neutralinojsを含めてPoC
              └─ いいえ → 現行Electronまたは要件の再整理

まとめ: 軽量化より、運用できる境界を選ぶ

良い移行はベンチマークの一行で決まりません。ユーザーが本当に行う仕事、端末のどの能力へ届くか、誰が更新・署名・障害対応を担うかを対象OSで検証し、運用できる境界を選びます。Tauri、Wails、Neutralinojsはいずれも有力な選択肢ですが、既存Electronを改善する方が合理的な場合もあります。選択の品質は、移行後のランタイム名ではなく、権限・配布・失敗経路を説明できることに現れます。

公式ドキュメント

最新の記事