AI

デスクトップアプリ比較:Tauri vs Electron vs Wails でクロスプラットフォームアプリを構築する

オープンソースラボ編集部2026年6月14日

デスクトップアプリ比較:Tauri vs Electron vs Wails でクロスプラットフォームアプリを構築する

WebフロントエンドエンジニアがWindows・macOS・Linuxで動作するデスクトップアプリを開発できるクロスプラットフォームフレームワークが充実しています。Tauri(Rust製・超軽量)・Electron(Node.js製・最大シェア)・Wails(Go製・軽量)の3つが2026年のクロスプラットフォームデスクトップアプリのデファクトスタンダードです。

デスクトップアプリフレームワークを選ぶ理由

  • 既存WebスキルでデスクトップUI: React/Vue/SvelteのコードをそのままデスクトップGUIに流用
  • ネイティブAPI: ファイルシステム・システムトレイ・通知・Webview外のOS機能にアクセス
  • オフライン動作: ブラウザ拡張やSaaS不要のスタンドアロンアプリとして配布
  • パフォーマンス: Chromeを丸ごと同梱するElectronに対してTauri/WailsはシステムのWebviewを使いバイナリが小さい

主要フレームワークの概要

Tauri

2021年公開、Rust製のOSSです。GitHubスター86k+。Rust + WebviewでElectronの1/10のバイナリサイズを実現するフレームワークで、フロントエンドは任意のWeb技術(React・Vue・Svelte)を使用します。Tauri v2ではAndroid・iOSのモバイル対応も追加されました。

# Tauri v2 セットアップ(Vite + React + TypeScript)
npm create tauri-app@latest my-app --   --template react-ts   --manager npm

cd my-app
npm install
npm run tauri dev
// src-tauri/src/lib.rs: Rustバックエンドのコマンド定義
use tauri::{AppHandle, Manager};
use std::path::PathBuf;

// フロントエンドからコマンドを受け取る
#[tauri::command]
async fn read_file(path: String) -> Result<String, String> {
    std::fs::read_to_string(&path)
        .map_err(|e| format!("ファイル読み込みエラー: {}", e))
}

#[tauri::command]
async fn write_file(path: String, content: String) -> Result<(), String> {
    std::fs::write(&path, content)
        .map_err(|e| format!("ファイル書き込みエラー: {}", e))
}

#[tauri::command]
async fn get_app_data_dir(app: AppHandle) -> Result<String, String> {
    let data_dir = app.path().app_data_dir()
        .map_err(|e| format!("パス取得エラー: {}", e))?;
    Ok(data_dir.to_string_lossy().to_string())
}

// システムトレイアイコン
#[tauri::command]
async fn show_notification(title: String, body: String, app: AppHandle) {
    let _ = app.notification()
        .title(&title)
        .body(&body)
        .show();
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_fs::init())
        .plugin(tauri_plugin_notification::init())
        .plugin(tauri_plugin_dialog::init())
        .invoke_handler(tauri::generate_handler![
            read_file,
            write_file,
            get_app_data_dir,
            show_notification,
        ])
        .run(tauri::generate_context!())
        .expect("Tauriアプリの起動に失敗");
}
// src/App.tsx: React フロントエンドからTauriコマンドを呼び出す
import { invoke } from '@tauri-apps/api/core'
import { open, save } from '@tauri-apps/plugin-dialog'
import { useState } from 'react'

export default function App() {
  const [content, setContent] = useState('')
  const [filePath, setFilePath] = useState('')

  const openFile = async () => {
    const selected = await open({
      multiple: false,
      filters: [{ name: 'テキスト', extensions: ['txt', 'md'] }],
    })
    if (selected) {
      const text = await invoke<string>('read_file', { path: selected })
      setContent(text)
      setFilePath(selected as string)
    }
  }

  const saveFile = async () => {
    const path = await save({ defaultPath: filePath || 'document.txt' })
    if (path) {
      await invoke('write_file', { path, content })
      await invoke('show_notification', { title: '保存完了', body: `${path}に保存しました` })
    }
  }

  return (
    <div style={{ padding: 20 }}>
      <button onClick={openFile}>ファイルを開く</button>
      <textarea value={content} onChange={e => setContent(e.target.value)} rows={20} style={{ width: '100%' }} />
      <button onClick={saveFile}>保存</button>
    </div>
  )
}

Electron

2013年公開(GitHub製)、TypeScript/JavaScript製のOSSです。GitHubスター115k+。VS Code・Slack・Discordが使う実績最大のデスクトップフレームワークで、Node.jsのAPIがフル利用できます。Chromiumを同梱するためバイナリが200MB前後と大きいですが、エコシステムと実績が圧倒的です。

// main.ts: Electronメインプロセス(Node.js)
import { app, BrowserWindow, ipcMain, dialog, Notification, Tray, Menu, nativeImage } from 'electron'
import path from 'path'
import fs from 'fs'

let mainWindow: BrowserWindow | null
let tray: Tray | null

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true,
    },
  })

  // 開発時: Vite devサーバー、本番: dist/index.html
  if (process.env.NODE_ENV === 'development') {
    mainWindow.loadURL('http://localhost:5173')
  } else {
    mainWindow.loadFile(path.join(__dirname, '../dist/index.html'))
  }
}

// IPC: レンダラープロセスからのコマンドを受信
ipcMain.handle('read-file', async (_event, filePath: string) => {
  return fs.readFileSync(filePath, 'utf-8')
})

ipcMain.handle('open-dialog', async () => {
  const result = await dialog.showOpenDialog(mainWindow!, {
    filters: [{ name: 'テキスト', extensions: ['txt', 'md'] }],
  })
  return result.filePaths[0] || null
})

ipcMain.handle('show-notification', (_event, title: string, body: string) => {
  new Notification({ title, body }).show()
})

app.whenReady().then(() => {
  createWindow()

  // システムトレイ
  const icon = nativeImage.createFromPath(path.join(__dirname, 'icon.png'))
  tray = new Tray(icon)
  tray.setContextMenu(Menu.buildFromTemplate([
    { label: 'ウィンドウを表示', click: () => mainWindow?.show() },
    { label: '終了', role: 'quit' },
  ]))
})

Wails

2020年公開、Go製のOSSです。GitHubスター26k+。GoバックエンドとWebフロントエンドを組み合わせた軽量フレームワークで、Tauriより小さいバイナリ(約4MB)とGoのシンプルさが魅力です。

// main.go: Wailsバックエンド
package main

import (
    "context"
    "fmt"
    "os"
    "embed"
    "github.com/wailsapp/wails/v2"
    "github.com/wailsapp/wails/v2/pkg/options"
    "github.com/wailsapp/wails/v2/pkg/runtime"
)

//go:embed all:frontend/dist
var assets embed.FS

type App struct {
    ctx context.Context
}

func (a *App) startup(ctx context.Context) { a.ctx = ctx }

func (a *App) ReadFile(path string) (string, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return "", fmt.Errorf("ファイル読み込みエラー: %w", err)
    }
    return string(data), nil
}

func (a *App) OpenFileDialog() (string, error) {
    return runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
        Filters: []runtime.FileFilter{{DisplayName: "Text Files", Pattern: "*.txt;*.md"}},
    })
}

func main() {
    app := &App{}
    wails.Run(&options.App{
        Title: "My Wails App",
        Width: 1024,
        Height: 768,
        AssetServer: &assetserver.Options{Assets: assets},
        OnStartup: app.startup,
        Bind: []interface{}{app},
    })
}

機能比較表

比較項目TauriElectronWails
バイナリサイズ✅ ~6MB❌ ~200MB✅ ~4MB
バックエンド言語RustNode.jsGo
モバイル対応✅(v2)
エコシステム成長中✅ 最大
GitHub Stars86k+115k+26k+

デスクトップアプリフレームワークはDevOpsカテゴリ/categories/devopsのCI/CD(GitHub Actions)でWindows・macOS・Linux向けバイナリをビルドして自動リリースするパイプラインと組み合わせて配布を自動化します。LLM Toolsカテゴリ/categories/llm-toolsのOllama・Whisperとローカルで統合してオフラインAIアシスタントデスクトップアプリを構築するパターンが注目されています。

FAQ

Q. TauriとElectronのバイナリサイズはなぜ違うのですか?

A. Electronは独自のChromiumランタイムをバンドルするのに対し、TauriはOSのシステムWebViewを使用するからです。Electronのバンドル内訳: Chromiumレンダリングエンジン(約150MB)+ Node.jsランタイム(約30MB)+ アプリコード(数MB)=合計200MB前後。Tauriのバンドル内訳: Rustバイナリ(約3〜4MB)+ アプリコード(数MB)=合計6MB前後。システムWebViewの違い: Windows→WebView2(Edge/Chromiumベース)、macOS→WKWebView(Safari/WebKitベース)、Linux→WebKitGTK。注意: システムWebViewはOSのバージョンに依存するためレイアウトの微差が生じる可能性があります。Electronはどの環境でも同一のChromiumで動作するため一貫性が高いです。

Q. ElectronアプリをmacOSでノータリゼーション(公証)するには?

A. Apple Developer Programへの加入($99/年)とelectron-builderのコード署名設定が必要です。手順: ①Apple Developer Programに登録②Xcodeでコード署名証明書(Developer ID Application)を発行③electron-builder.config.jsmac: {identity: 'Developer ID Application: Your Name (XXXXXXXXXX)', notarize: {teamId: 'XXXXXXXXXX'}}を設定④npm run buildでビルド時に自動署名・ノータリゼーション・ステープリングが実行。CI(GitHub Actions): apple_idapple_app_specific_passwordapple_team_idをGitHub Secretsに設定してactions/macos-12ランナーで実行。Tauriのnotarize: tauri.conf.jsonbundle.macOS.signing_identitybundle.macOS.notarizeで同様に設定できます。

Q. Tauriアプリで自動アップデートを実装するには?

A. **tauri-plugin-updater(v2)またはElectronはelectron-updater**で実装します。Tauriアップデーター: ①npm install @tauri-apps/plugin-updatertauri.conf.jsonplugins.updater.endpointsにアップデートチェックURLを設定③Rustコード: tauri_plugin_updater::UpdaterExt::update_check()でアップデートを確認してインストール④GitHub Releasesをエンドポイントとして使用(update.jsonをリリースに添付)。Electronアップデーター: electron-updaterパッケージ+GitHub Releasesまたはカスタムサーバー→autoUpdater.checkForUpdatesAndNotify()で起動時に自動チェック・通知・インストール。

Q. WailsとTauriのどちらを選ぶべきですか?

A. Goに慣れているチーム・シンプルさ重視ならWailsRust性能・モバイル将来対応・活発なコミュニティならTauriが向いています。Tauri優位: ①GitHubスター86k(Wailsの3倍)で知見・プラグインが豊富②v2でAndroid/iOS対応(Wailsは未対応)③Rustによるメモリ安全性保証。Wails優位: ①Goの学習コストが低くRustより習得しやすい②バイナリサイズが最小(4MB前後)③Goのnet/httpパッケージやgoroutineが活かせる。どちらもElectronより軽量でWeb技術でUIを構築できますが、エコシステムと採用実績ではTauriが優勢です。

まとめ

ユースケース推奨ツール
軽量・モバイル対応・Rust性能Tauri
VS Code級・Node.js・最大エコシステムElectron
Go・最小バイナリ・シンプルWails

関連外部リソース

他の記事も読む

Let's Build Together

OSS導入、自社だけで悩まない。

ツール選定から構築・運用・AI活用まで、オープンソースラボ運営元のClasslessが伴走します。初回のご相談は無料です。