understanding-tauri-architecture について
Tauri を使う開発者向けのデスクトップアプリ構造解説です。Rust コア、WebView フロントエンド、IPC、階層化されたセキュリティモデルを説明します。
主な機能
- 01コアとシェルのアーキテクチャ
- 02Rust バックエンドの役割
- 03ネイティブ WebView の統合
- 04コマンドとイベントによる IPC
- 05ケイパビリティと権限モデル
活用シーン
- 01Tauri アプリのレイヤー理解
- 02フロントエンドとバックエンド間の通信設計
- 03Tauri の権限境界の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dchuk/ claude-code-tauri-skills --skill understanding-tauri-architectureインストール後、Claude Code で/understanding-tauri-architectureを入力して読み込まれたか確認します。
詳細
Tauri のアーキテクチャ
Tauri は、Rust バックエンドと、ネイティブ WebView でレンダリングされる HTML/CSS/JavaScript を組み合わせてデスクトップアプリを構築するための、複数の言語に対応したツールキットです。このドキュメントでは、アーキテクチャの基本概念について説明します。
アーキテクチャの概要
+------------------------------------------------------------------+
| TAURI APPLICATION |
+------------------------------------------------------------------+
| |
| +---------------------------+ +---------------------------+ |
| | FRONTEND (Shell) | | BACKEND (Core) | |
| |---------------------------| |---------------------------| |
| | | | | |
| | HTML / CSS / JavaScript | | Rust Code | |
| | (or any web framework) | | (tauri crate + app) | |
| | | | | |
| | - React, Vue, Svelte, | | - System access | |
| | Solid, etc. | | - File operations | |
| | - Standard web APIs | | - Native features | |
| | - Tauri JS API | | - Plugin system | |
| | | | | |
| +-------------+-------------+ +-------------+-------------+ |
| | | |
| | IPC (Message Passing) | |
| +<------------------------------->+ |
| | Commands & Events | |
| |
| +------------------------------------------------------------+ |
| | WEBVIEW (TAO + WRY) | |
| |------------------------------------------------------------| |
| | - Platform-native webview (not bundled) | |
| | - Windows: WebView2 (Edge/Chromium) | |
| | - macOS: WKWebView (Safari/WebKit) | |
| | - Linux: WebKitGTK | |
| +------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| OPERATING SYSTEM |
| - Windows, macOS, Linux, iOS, Android |
+------------------------------------------------------------------+
コアとシェルの設計
Tauri はコア・シェルアーキテクチャを採用しており、アプリケーションは明確に分かれた 2 つの層で構成されます。
コア(Rust バックエンド)
コアは Rust ベースのバックエンドで、システムレベルのすべての操作を処理します。
- システムアクセス:ファイルシステム、ネットワーク、プロセス
- ネイティブ機能:通知、ダイアログ、クリップボード
- セキュリティの適用:権限の検証、ケイパビリティの確認
- プラグイン管理:プラグインによる機能の拡張
- アプリのライフサイクル:ウィンドウ管理、アップデート、設定
コアはフロントエンドにシステムへの直接アクセスを決して公開しません。すべてのやり取りは、検証済みの IPC チャネルを通じて行われます。
シェル(フロントエンド)
シェルは WebView でレンダリングされるユーザーインターフェース層です。
- Web 技術:HTML、CSS、JavaScript/TypeScript
- フレームワークに依存しない:React、Vue、Svelte、Solid、またはバニラ JS で動作します
- サンドボックスでの実行:WebView のセキュリティサンドボックス内で実行されます
- Tauri API へのアクセス:
@tauri-apps/apiを通じてバックエンドを呼び出します
エコシステムの主要コンポーネント
tauri Crate
中心的なオーケストレーターで、以下を行います。
- コンパイル時に
tauri.conf.jsonを読み込みます - WebView へのスクリプトの挿入を管理します
- システム操作 API を提供します
- アプリケーションのアップデートを処理します
- ランタイム、マクロ、ユーティリティを統合します
tauri-runtime
Tauri と低レベルの WebView ライブラリをつなぐ層です。プラットフォーム固有の WebView 操作を抽象化し、Tauri のその他の部分がプラットフォームに依存しない状態を保てるようにします。
tauri-macros と tauri-codegen
以下のコンパイル時コードを生成します。
- コマンドハンドラー(
#[tauri::command]) - コンテキストと設定の解析
- アセットの埋め込みと圧縮
TAO(ウィンドウ管理)
クロスプラットフォーム対応のウィンドウ作成ライブラリ(Winit からフォーク)です。
- アプリケーションのウィンドウを作成および管理します
- メニューバーとシステムトレイを処理します
- Windows、macOS、Linux、iOS、Android に対応しています
WRY(WebView レンダリング)
クロスプラットフォーム対応の WebView レンダリングライブラリです。
- プラットフォームごとの WebView 実装を抽象化します
- WebView とネイティブ間の通信を処理します
- JavaScript の評価とイベントの橋渡しを管理します
WebView の統合
Tauri はブラウザーエンジンをバンドルするのではなく、オペレーティングシステムのネイティブ WebView を使用します。
+-------------------+---------------------------+
| Platform | WebView Engine |
+-------------------+---------------------------+
| Windows | WebView2 (Edge/Chromium) |
| macOS | WKWebView (Safari/WebKit) |
| Linux | WebKitGTK |
| iOS | WKWebView |
| Android | Android WebView |
+-------------------+---------------------------+
ネイティブ WebView の利点
- バイナリサイズの縮小:ブラウザーエンジンをバンドルする必要がありません(約 600KB 対 約 150MB)
- セキュリティ:OS ベンダーは、アプリ開発者がアプリを再ビルドするよりも速く WebView の脆弱性にパッチを適用します
- パフォーマンス:オペレーティングシステムとのネイティブな統合
- 一貫性:ユーザーには使い慣れたレンダリング動作が表示されます
考慮事項
- プラットフォーム間でレンダリングにわずかな違いがあります
- 利用可能な機能は OS の WebView バージョンによって異なります
- テストではすべての対象プラットフォームを網羅する必要があります
プロセス間通信(IPC)
Tauri は、フロントエンドとバックエンド間の通信に非同期メッセージパッシングを実装しています。コアが悪意のあるリクエストを拒否できるため、共有メモリよりも安全です。
IPC フロー図
+------------------+ +------------------+
| Frontend | | Rust Backend |
| (JavaScript) | | (Core) |
+--------+---------+ +--------+---------+
| |
| 1. invoke('command', {args}) |
+---------------------------------------->|
| |
| [Request serialized as JSON-RPC] |
| |
| 2. Validate request |
| 3. Check permissions |
| 4. Execute command |
| |
| 5. Return Result<T, E> |
|<----------------------------------------+
| |
| [Response serialized as JSON] |
| |
2 つの IPC プリミティブ
コマンド(リクエスト・レスポンス)
型安全な、フロントエンドからバックエンドへの関数呼び出しです。
// Rust backend
#[tauri::command]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
// Register in builder
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
// JavaScript frontend
import { invoke } from '@tauri-apps/api/core';
const greeting = await invoke('greet', { name: 'World' });
console.log(greeting); // "Hello, World!"
主な特徴:
- JSON-RPC プロトコル上に構築されています
- すべての引数は JSON にシリアライズ可能である必要があります
- 結果を受け取る Promise を返します
- 非同期 Rust 関数に対応しています
- アプリの状態、ウィンドウハンドルなどにアクセスできます
イベント(送信後の応答なし)
双方向の非同期通知です。
// Frontend: emit event
import { emit } from '@tauri-apps/api/event';
emit('user-action', { action: 'clicked' });
// Frontend: listen for events
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen('download-progress', (event) => {
console.log(event.payload);
});
// Backend: listen for events
use tauri::Listener;
app.listen("user-action", |event| {
println!("User action: {}", event.payload());
});
// Backend: emit events
app.emit("download-progress", 50)?;
主な特徴:
- 戻り値はありません(一方向)
- フロントエンドとバックエンドの両方からイベントの発行とリッスンができます
- ライフサイクルイベントや状態の変更に最適です
- コンパイル時の型チェックは行われません
セキュリティモデルの概要
Tauri は、アプリケーションとユーザーのシステムの両方を保護するために、複数層のセキュリティを実装しています。
信頼境界モデル
+------------------------------------------------------------------+
| UNTRUSTED ZONE |
| +------------------------------------------------------------+ |
| | WebView Frontend | |
| | - JavaScript code (potentially from remote sources) | |
| | - User input | |
| | - Third-party libraries | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+
|
[TRUST BOUNDARY]
[IPC Layer validates all requests]
|
+------------------------------------------------------------------+
| TRUSTED ZONE |
| +------------------------------------------------------------+ |
| | Rust Backend | |
| | - Your Rust code | |
| | - Tauri core | |
| | - System access (gated by permissions) | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+
セキュリティレイヤー
- WebView サンドボックス:フロントエンドコードは WebView のセキュリティサンドボックス内で実行されます
- IPC 検証:信頼境界を越えるすべてのメッセージが検証されます
- ケイパビリティ:各ウィンドウがアクセスできる権限を定義します
- 権限:許可する操作を細かく制御します
- スコープ:コマンドの動作を制限します(例:ファイルアクセスを特定のディレクトリに限定する)
- CSP:コンテンツセキュリティポリシーによって、フロントエンドコードが実行できる操作を制限します
ケイパビリティシステム
ケイパビリティは、特定のウィンドウに付与する権限を制御します。
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main-window-capability",
"description": "Permissions for the main application window",
"windows": ["main"],
"permissions": [
"core:path:default",
"core:window:allow-set-title",
"fs:read-files",
"fs:scope-app-data"
]
}
ケイパビリティは、src-tauri/capabilities/ に JSON または TOML ファイルとして定義します。
権限の構造
Capability
|
+-- windows: ["main", "settings"] // Which windows
|
+-- permissions: // What's allowed
|
+-- "plugin:action" // Allow specific action
+-- "plugin:scope-xxx" // Scope restrictions
デフォルトのセキュリティ態勢
- デフォルトで拒否:コマンドは明示的に許可する必要があります
- リモートアクセスなし:デフォルトでは、バンドルされたコードのみが Tauri API にアクセスできます
- ウィンドウの分離:各ウィンドウは独自のケイパビリティセットを持ちます
- コンパイル時チェック:多くのセキュリティ設定はビルド時に検証されます
Rust バックエンドの構造
一般的な Tauri バックエンドは、次の構造に従います。
src-tauri/
+-- Cargo.toml # Rust dependencies
+-- tauri.conf.json # Tauri configuration
+-- capabilities/ # Permission definitions
| +-- main.json
+-- src/
+-- main.rs # Entry point (desktop)
+-- lib.rs # Core app logic
+-- commands/ # Command modules
| +-- mod.rs
| +-- file_ops.rs
+-- state.rs # App state management
エントリーポイントのパターン
// src-tauri/src/lib.rs
mod commands;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![
commands::greet,
commands::read_file,
])
.manage(AppState::default())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
コマンドのパターン
// Basic command
#[tauri::command]
fn simple_command() -> String {
"Hello".into()
}
// With arguments (camelCase from JS, snake_case in Rust)
#[tauri::command]
fn with_args(user_name: String, age: u32) -> String {
format!("{} is {} years old", user_name, age)
}
// With error handling
#[tauri::command]
fn fallible() -> Result<String, String> {
Ok("Success".into())
}
// Async command
#[tauri::command]
async fn async_command() -> Result<String, String> {
tokio::time::sleep(Duration::from_secs(1)).await;
Ok("Done".into())
}
// Accessing app state
#[tauri::command]
fn with_state(state: tauri::State<'_, AppState>) -> String {
state.get_value()
}
// Accessing window
#[tauri::command]
fn with_window(window: tauri::WebviewWindow) -> String {
window.label().to_string()
}
ランタイムはバンドルされません
Tauri はランタイムを同梱しません。最終的なバイナリは次のとおりです。
- Rust コードをネイティブのマシンコードに直接コンパイルします
- フロントエンドのアセットをバイナリに埋め込みます
- システムのネイティブ WebView を使用します
- 小さく、高速な実行ファイルになります
そのため、Tauri アプリのリバースエンジニアリングは、JavaScript がバンドルされた Electron アプリと比べて容易ではありません。
まとめ
| コンポーネント | 役割 |
|---|---|
| コア(Rust) | システムアクセス、セキュリティ、ビジネスロジック |
| シェル(フロントエンド) | UI の描画、ユーザー操作 |
| WebView(TAO+WRY) | プラットフォームネイティブな描画ブリッジ |
| IPC(コマンド/イベント) | レイヤー間で安全にメッセージをやり取りします |
| ケイパビリティ | ウィンドウごとの権限制御 |
アーキテクチャでは、次の点を優先しています。
- セキュリティ:複数の保護レイヤー、信頼境界
- パフォーマンス:ネイティブコード、ランタイムの非バンドル
- サイズ:バイナリのフットプリントを最小限に抑えます
- 柔軟性:あらゆるフロントエンドフレームワークに対応し、高機能な Rust バックエンドを備えます