MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Tauriの基礎 - プロジェクト構造のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Tauriの基礎 - プロジェクト構造
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Tauriは、RustバックエンドとWebフロントエンドを組み合わせてデスクトップアプリケーションを開発するためのフレームワークである。<br> フロントエンドにはReact、Vue、Svelte等の任意のフレームワークを使用でき、バックエンドはRustで記述する。<br> <br> Tauriプロジェクトは、フロントエンド用のディレクトリとRustバックエンド用の <u>src-tauri/</u> ディレクトリで構成される。<br> この2層構造により、Web技術の柔軟性とRustのパフォーマンスを両立できる。<br> <br> フロントエンドとバックエンドの通信には、Tauriが提供する <u>>invoke API</u> を使用する。<br> フロントエンドからRustのコマンドを呼び出し、その結果を受け取ることができる。<br> <br> Tauri v2では、セキュリティ強化のために <u>capabilities/</u> ディレクトリで権限管理を行う。<br> アプリケーションが必要とする機能のみを明示的に許可することにより、セキュリティリスクを最小限に抑える。<br> <br> 主な特徴は以下の通りである。<br> * Rustバックエンドによる高速で安全な処理 * Webフロントエンドによる柔軟なUI開発 * クロスプラットフォーム対応 (Windows、MacOS、Linux) * 小さなバイナリサイズと低いメモリ消費 * Tauri v2による強化された権限管理システム <br><br> == ディレクトリ構成 == Tauriプロジェクトの標準的なディレクトリ構成を以下に示す。<br> <br> . ├── package.json ├── index.html ├── vite.config.ts ├── node_modules/ ├── dist/ ├── src/ │ ├── main.tsx │ ├── App.tsx │ └── components/ └── src-tauri/ ├── Cargo.toml ├── build.rs ├── tauri.conf.json ├── src/ │ ├── main.rs │ ├── lib.rs │ └── commands.rs ├── icons/ └── capabilities/ └── default.json <br> ==== ディレクトリの役割 ==== * <u>src/</u> *: フロントエンドのソースコードを配置するディレクトリ * <u>src-tauri/</u> *: Rustバックエンドのプロジェクトディレクトリ (Cargoパッケージとして管理) * <u>src-tauri/capabilities/</u> *: Tauri v2の権限設定ファイルを配置するディレクトリ * <u>src-tauri/icons/</u> *: アプリケーションアイコンを配置するディレクトリ <br> ==== 自動生成ディレクトリ ==== * <u>node_modules/</u> *: npmパッケージのインストール先 (<code>npm install</code> コマンドで自動生成) * <u>dist/</u> *: フロントエンドのビルド成果物 (<code>npm run build</code> コマンドで生成) * <u>src-tauri/target/</u> *: Rustのビルド成果物 *: (デバッグ: <u>target/debug/</u>、リリース: <u>target/release/</u>) <br><br> == 主要ファイルの役割 (フロントエンド) == ==== main.tsx ==== <code>main.tsx</code> は、Reactアプリケーションのエントリーポイントである。<br> <syntaxhighlight lang="typescript"> import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( <React.StrictMode><App /></React.StrictMode>, ); </syntaxhighlight> <br> ==== App.tsx ==== <code>App.tsx</code> は、アプリケーションのメインコンポーネントである。<br> <code>invoke</code> 関数を使用して、Rustバックエンドのコマンドを呼び出す。<br> <syntaxhighlight lang="typescript"> import { useState } from "react"; import { invoke } from "@tauri-apps/api/core"; function App() { const [greeting, setGreeting] = useState(""); async function greet(name: string) { try { const result = await invoke<string>("greet", { name }); setGreeting(result); } catch (err) { console.error("Error:", err); } } return ( <div> <button onClick={() => greet("World")}>Greet</button> <p>{greeting}</p> </div> ); } export default App; </syntaxhighlight> <br> ==== invoke関数 ==== <code>invoke</code> 関数は、フロントエンドからRustバックエンドのコマンドを呼び出すためのAPIである。<br> <code>@tauri-apps/api/core</code> からインポートして使用する。<br> * 第1引数: Rust側で定義したコマンド名 (文字列) * 第2引数: コマンドに渡す引数 (オブジェクト形式、省略可能) * 戻り値: Rustコマンドの実行結果を含むPromise <br> エラーハンドリング例:<br> <syntaxhighlight lang="typescript"> async function callRustCommand() { try { const result = await invoke<string>("get_version"); console.log("Version:", result); } catch (error) { console.error("Command failed:", error); } } </syntaxhighlight> <br> ==== index.html ==== <code>index.html</code> は、アプリケーションのHTMLエントリーポイントである。<br> <syntaxhighlight lang="html"> <!DOCTYPE html> <html lang="ja"> <head><meta charset="UTF-8" /><title>Tauri App</title></head> <body> <div id="root"></div> <script type="module" src="/src/main.tsx"></script> </body> </html> </syntaxhighlight> <br> ==== vite.config.ts ==== <code>vite.config.ts</code> は、Viteの設定ファイルである。<br> <syntaxhighlight lang="typescript"> import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [react()], clearScreen: false, server: { port: 1420, strictPort: true }, }); </syntaxhighlight> <br><br> == 主要ファイルの役割 (バックエンド) == ==== main.rs ==== <code>main.rs</code> は、Rustアプリケーションのエントリーポイントである。<br> 実際の処理は <code>lib.rs</code> に委譲する。<br> <syntaxhighlight lang="rust"> #![cfg_attr(all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows")] fn main() { app_lib::run() } </syntaxhighlight> <br> Windows環境では、リリースビルド時にコンソールウィンドウを表示しないように設定している。<br> <br> ==== lib.rs ==== <code>lib.rs</code> は、Tauriアプリケーションのメインロジックを記述するファイルである。<br> <syntaxhighlight lang="rust"> #![cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![greet, get_version]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } #[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}!", name) } </syntaxhighlight> <br> ==== コマンド定義 ==== Tauriでフロントエンドから呼び出し可能なコマンドを定義するには、<code>#[tauri::command]</code> アトリビュートを使用する。<br> <br> ===== 基本的なコマンドと戻り値 ===== <syntaxhighlight lang="rust"> #[tauri::command] fn simple_command() { println!("Command called"); } #[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}!", name) } </syntaxhighlight> <br> ===== 非同期コマンド (async) ===== <syntaxhighlight lang="rust"> #[tauri::command] async fn fetch_data(url: String) -> Result<String, String> { let response = reqwest::get(&url).await.map_err(|e| e.to_string())?; response.text().await.map_err(|e| e.to_string()) } </syntaxhighlight> <br> ===== 引数の命名規則 (rename_all) ===== Rustのsnake_caseとJavaScriptのcamelCaseの違いを吸収する。<br> <syntaxhighlight lang="rust"> #[tauri::command] fn process_data(#[serde(rename = "userName")] user_name: String) -> String { format!("User: {}", user_name) } </syntaxhighlight> <br> ===== エラーハンドリング (Result型) ===== <syntaxhighlight lang="rust"> #[tauri::command] fn divide(a: i32, b: i32) -> Result<i32, String> { if b == 0 { return Err("Division by zero".to_string()); } Ok(a / b) } </syntaxhighlight> <br> ==== build.rs ==== <code>build.rs</code> は、ビルド時に実行されるスクリプトである。<br> <syntaxhighlight lang="rust"> fn main() { tauri_build::build() } </syntaxhighlight> <br><br> == 別モジュールへのコマンド定義 == コマンドが増えてくると、<code>lib.rs</code> が肥大化する。<br> コマンドを別のモジュールに分割して管理する方法を説明する。<br> <br> ==== commands.rsの作成 ==== <syntaxhighlight lang="rust"> // src-tauri/src/commands.rs #[tauri::command] pub fn greet(name: &str) -> String { format!("Hello, {}!", name) } #[tauri::command] pub fn get_version() -> String { env!("CARGO_PKG_VERSION").to_string() } </syntaxhighlight> <br> ==== lib.rsでのインポート ==== <syntaxhighlight lang="rust"> // src-tauri/src/lib.rs mod commands; #![cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![commands::greet, commands::get_version]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } </syntaxhighlight> <br><br> == 状態管理 == Tauriでは、アプリケーション全体で共有される状態を管理できる。<br> <code>tauri::State</code> を使用して、複数のコマンド間でデータを共有する。<br> <br> <syntaxhighlight lang="rust"> use std::sync::Mutex; use tauri::State; struct AppState { counter: Mutex<i32> } #[tauri::command] fn get_counter(state: State<AppState>) -> i32 { *state.counter.lock().unwrap() } #[tauri::command] fn increment_counter(state: State<AppState>) -> i32 { let mut counter = state.counter.lock().unwrap(); *counter += 1; *counter } pub fn run() { tauri::Builder::default() .manage(AppState { counter: Mutex::new(0) }) .invoke_handler(tauri::generate_handler![get_counter, increment_counter]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } </syntaxhighlight> <br><br> == 設定ファイル == ==== Cargo.toml ==== <u>Cargo.toml</u> ファイルは、Rustプロジェクトの設定ファイルである。<br> <br> <syntaxhighlight lang="toml"> [package] name = "my-tauri-app" version = "0.1.0" edition = "2021" [build-dependencies] tauri-build = { version = "2.0.0" } [dependencies] serde = { version = "1.0", features = ["derive"] } tauri = { version = "2.0.0", features = [] } [profile.release] panic = "abort" lto = true opt-level = "s" strip = true </syntaxhighlight> <br> <center> {| class="wikitable" |+ Cargo.tomlファイルの主要な設定項目 ! 設定項目 !! 説明 |- | <code>[package]</code> || パッケージの基本情報 |- | <code>[build-dependencies]</code> || ビルド時に必要な依存クレート |- | <code>[dependencies]</code> || 実行時に必要な依存クレート |- | <code>[profile.release]</code> || リリースビルドの最適化設定 |} </center> <br> ==== package.json ==== <code>package.json</code> ファイルは、Node.jsプロジェクトの設定ファイルである。<br> <br> <syntaxhighlight lang="json"> { "scripts": { "dev": "vite", "build": "tsc && vite build", "tauri": "tauri" }, "dependencies": { "@tauri-apps/api": "^2.0.0", "react": "^18.2.0" }, "devDependencies": { "@tauri-apps/cli": "^2.0.0", "typescript": "^5.0.0", "vite": "^5.0.0" } } </syntaxhighlight> <br> ==== tauri.conf.json ==== <u>tauri.conf.json</u> ファイルは、Tauriアプリケーションの設定ファイルである。<br> <br> <syntaxhighlight lang="json"> { "productName": "My Tauri App", "version": "0.1.0", "identifier": "com.example.myapp", "build": { "beforeDevCommand": "npm run dev", "devUrl": "http://localhost:1420", "frontendDist": "../dist" }, "app": { "windows": [{ "title": "My Tauri App", "width": 800, "height": 600 }] } } </syntaxhighlight> <br><br> == capabilities/ディレクトリ == <u>capabilities/</u> ディレクトリは、Tauri v2で導入された権限管理システムの設定ファイルを配置する。<br> <br> ==== Tauri v2権限システム ==== Tauri v2では、セキュリティ強化のためにcapabilities (権限) システムが導入された。<br> アプリケーションが必要とする機能のみを明示的に許可することにより、セキュリティリスクを最小限に抑える。<br> <br> * プリンシパル (主体) *: 権限を付与する対象 (ウィンドウ、Webビュー等) * 権限 (Permission) *: 特定の機能へのアクセス許可 * ケイパビリティ (Capability) *: プリンシパルと権限の組み合わせ <br> ==== 設定例 ==== <syntaxhighlight lang="json"> { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "main-capability", "windows": ["main"], "permissions": [ "core:path:default", "core:event:default", "core:window:default", "core:app:default", "shell:allow-open" ] } </syntaxhighlight> <br> <center> {| class="wikitable" |+ 主な権限の一覧 ! 権限 !! 説明 |- | <u>core:path:default</u> || ファイルパス操作の基本権限 |- | <u>core:event:default</u> || イベントシステムの基本権限 |- | <u>core:window:default</u> || ウィンドウ操作の基本権限 |- | <u>core:app:default</u> || アプリケーション情報へのアクセス権限 |- | <u>shell:allow-open</u> || 外部プログラムの実行許可 |- | <u>dialog:default</u> || ファイルダイアログの基本権限 |- | <u>fs:default</u> || ファイルシステムの基本権限 |} </center> <br> ==== プラットフォーム固有のcapability ==== <syntaxhighlight lang="json"> { "identifier": "platform-capability", "windows": ["main"], "permissions": [ { "identifier": "shell:allow-open", "platforms": ["macOS", "windows"] } ] } </syntaxhighlight> <br><br> == icons/ディレクトリ == <u>icons/</u> ディレクトリには、アプリケーションのアイコンファイルを配置する。<br> <br> <center> {| class="wikitable" |+ アイコンファイルの種類 ! ファイル名 !! 用途 !! 対応プラットフォーム |- | <u>32x32.png</u> || 小サイズアイコン || 全プラットフォーム |- | <u>128x128.png</u> || 中サイズアイコン || 全プラットフォーム |- | <u>icon.icns</u> || MacOS用アイコン || MacOS |- | <u>icon.ico</u> || Windows用アイコン || Windows |} </center> <br> ==== アイコン生成コマンド ==== Tauri CLIを使用して、ソース画像から各プラットフォーム用のアイコンを一括生成できる。<br> <br> npm run tauri icon /path/to/source-icon.png <br><br> == 実用例 == フロントエンドからRustコマンドを呼び出す例を示す。<br> <br> ==== コンポーネントからのRustコマンド呼び出し ==== <syntaxhighlight lang="typescript"> import { useState, useEffect } from "react"; import { invoke } from "@tauri-apps/api/core"; interface FileInfo { name: string; size: number; } function FileList() { const [files, setFiles] = useState<FileInfo[]>([]); const [loading, setLoading] = useState(false); async function loadFiles(directory: string) { setLoading(true); try { const result = await invoke<FileInfo[]>("list_files", { directory }); setFiles(result); } finally { setLoading(false); } } useEffect(() => { loadFiles("."); }, []); return ( <div> <h2>File List</h2> {loading && <p>Loading...</p>} <ul> {files.map((file) => ( <li key={file.name}>{file.name} ({file.size} bytes)</li> ))} </ul> </div> ); } export default FileList; </syntaxhighlight> <br> ==== 状態管理の例 ==== Rust側でアプリケーション状態を管理する例を示す。<br> <br> <syntaxhighlight lang="rust"> use std::sync::Mutex; use tauri::State; #[derive(Clone, serde::Serialize)] pub struct Todo { id: u32, text: String, completed: bool } pub struct TodoStore { todos: Mutex<Vec<Todo>> } #[tauri::command] pub fn get_todos(store: State<TodoStore>) -> Vec<Todo> { store.todos.lock().unwrap().clone() } #[tauri::command] pub fn add_todo(text: String, store: State<TodoStore>) -> Todo { let mut todos = store.todos.lock().unwrap(); let id = todos.len() as u32 + 1; let todo = Todo { id, text, completed: false }; todos.push(todo.clone()); todo } </syntaxhighlight> <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=Tauri,Rust,React,TypeScript,デスクトップアプリ,WebView,クロスプラットフォーム,Vite,プロジェクト構造,main.rs,lib.rs,App.tsx,Cargo.toml,capabilities,invoke,コマンド,フロントエンド,バックエンド,状態管理,非同期コマンド,エラーハンドリング,build.rs,commands.rs,tauri::State |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Rust]]
Tauriの基礎 - プロジェクト構造
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse