Tauriの基礎 - プラグインシステム

2026年3月5日 (木) 01:46時点におけるWiki (トーク | 投稿記録)による版 (ページの作成:「== 概要 == Tauri v2のプラグインシステムは、アプリケーションのコア機能を拡張するためのモジュラーアーキテクチャである。<br> プラグインはCargo crate (Rust) とNPMパッケージ (JavaScript/TypeScript) の組み合わせで構成されており、必要な機能のみを選択してアプリケーションに組み込むことができる。<br> <br> Tauri v2では、多くのコア機能が公式プラグイン…」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)

概要

Tauri v2のプラグインシステムは、アプリケーションのコア機能を拡張するためのモジュラーアーキテクチャである。
プラグインはCargo crate (Rust) とNPMパッケージ (JavaScript/TypeScript) の組み合わせで構成されており、必要な機能のみを選択してアプリケーションに組み込むことができる。

Tauri v2では、多くのコア機能が公式プラグインとして分離され、アプリケーションのサイズを最小限に抑えながら必要な機能を追加できるようになった。

プラグインのインストールは npm run tauri add <プラグイン名> コマンドで行い、自動的にRust側とフロントエンド側の両方に必要な依存関係が追加される。

セキュリティモデルとしてCapabilities設定によるパーミッション管理が導入されており、アプリケーションがアクセスできるリソースや機能を厳密に制御できる。

公式プラグインにはファイルシステム (fs)、ダイアログ (dialog)、HTTPクライアント (http)、シェル実行 (shell)、通知 (notification)、クリップボード操作 (clipboard-manager)、
設定ストア (store) 等があり、コミュニティプラグインも多数公開されている。


プラグインアーキテクチャ

Tauri v2のプラグインは、以下に示す3つのコンポーネントで構成される。

  • Rust crate
    バックエンド側のロジックを実装する。
    命名規則は、tauri-plugin-{name} である。
    Cargo.tomlファイルの dependencies に追加される。
  • NPMパッケージ
    フロントエンド側のAPIを提供する。
    命名規則は @tauri-apps/plugin-{name} である。
    package.jsonファイルの dependencies に追加される。
  • ネイティブライブラリ (任意)
    AndroidやiOS等のモバイルプラットフォーム向けのネイティブコード
    デスクトップアプリケーションのみの場合は不要である。


このアーキテクチャにより、Rustの高性能なバックエンド処理 と JavaScript / TypeScriptからのAPI呼び出しを両立している。


Tauri v1からの変更点

Tauri v1からv2への移行に伴い、プラグインシステムは大幅に刷新された。

  • 機能の分離
    v1ではコアに含まれていた多くの機能が、v2では公式プラグインとして分離された。
    アプリケーションのバンドルサイズを削減できる。
  • Capabilitiesベースのセキュリティ
    v1の許可リスト方式から、v2ではCapabilities設定によるパーミッション管理に変更された。
    よりきめ細かいアクセス制御が可能になった。
  • 統一されたインストールコマンド
    npm run tauri add コマンドにより、RustとNPMの両方の依存関係が自動的に管理される。



インストール方法

自動インストール

プラグインのインストールは、以下に示すコマンドを実行するだけで完了する。

# ファイルシステムプラグインをインストール
npm run tauri add fs

# ダイアログプラグインをインストール
npm run tauri add dialog

# HTTPクライアントプラグインをインストール
npm run tauri add http


このコマンドは、以下に示す処理を自動的に実行する。

  • Cargo.tomlファイルへの依存関係追加
    tauri-plugin-fsdependencies に追加される。
  • package.jsonファイルへの依存関係追加
    @tauri-apps/plugin-fsdependencies に追加される。
  • Capabilitiesファイルの更新
    必要なパーミッションが自動的に追加される。
  • Rustコードの初期化
    src-tauri/src/lib.rs にプラグインの初期化コードが追加される。


手動インストール

自動インストールがうまく動作しない場合は、手動でインストールすることも可能である。

まず、Rust側の依存関係を追加する。

 # src-tauri/Cargo.toml
 [dependencies]
 tauri-plugin-fs = "2"


次に、NPMパッケージをインストールする。

npm install @tauri-apps/plugin-fs


Rust側でプラグインを初期化する。

 // src-tauri/src/lib.rs
 fn main() {
    tauri::Builder::default()
       .plugin(tauri_plugin_fs::init())
       .run(tauri::generate_context!())
       .expect("error while running tauri application");
 }


最後に、Capabilitiesファイルにパーミッションを追加する。

 {
   "permissions": [
     "fs:default"
   ]
 }



Capabilities設定

Capabilitiesは、アプリケーションがアクセスできる機能やリソースを定義するセキュリティ設定である。

設定ファイルの場所

Capabilities設定は、以下に示すディレクトリにJSONファイルとして配置する。

src-tauri/capabilities/
├── default.json       # デフォルトのケーパビリティ
├── main-window.json   # メインウィンドウ用
└── admin.json         # 管理者ウィンドウ用


設定ファイルの構造

基本的なCapabilitiesファイルの構造を以下に示す。

 {
   "$schema": "../gen/schemas/desktop-schema.json",
   "identifier": "default",
   "description": "Capability for the main window",
   "windows": ["main"],
   "permissions": [
     "core:default",
     "fs:default",
     "dialog:default"
   ]
 }


Capabilitiesファイルのフィールド
フィールド 説明
identifier ケーパビリティの一意識別子
ファイル名と同じにすることが推奨される。
description ケーパビリティの説明
開発者が理解しやすい説明を記述する。
windows このケーパビリティを適用するウィンドウ名の配列
["*"] で全てのウィンドウに適用できる。
permissions 許可するパーミッションの配列
プラグインごとに定義されたパーミッションを指定する。



パーミッションの指定方法

パーミッションは、文字列またはオブジェクトで指定できる。

  • 文字列で指定する場合
     {
       "permissions": [
         "fs:default",
         "fs:allow-read",
         "fs:allow-write"
       ]
     }
    

  • オブジェクトで指定する場合 (スコープ付き)
     {
       "permissions": [
         {
           "identifier": "fs:allow-read",
           "allow": [
             { "path": "$APPDATA/**" },
             { "path": "$RESOURCE/**" }
           ]
         }
       ]
     }
    



デフォルトパーミッション

多くのプラグインは、{plugin}:default という形式のデフォルトパーミッションを提供している。

これには、一般的な使用に必要なパーミッションが含まれている。

主要なデフォルトパーミッション
パーミッション 説明
core:default Tauriコア機能への基本アクセス
fs:default アプリケーションディレクトリへの読み書き
dialog:default ファイルダイアログとメッセージダイアログ
http:default HTTPリクエストの基本機能
shell:default シェルコマンドの基本実行



公式プラグイン一覧

下表に、Tauri v2で提供される公式プラグインの一覧を示す。

公式プラグイン一覧
プラグイン名 説明 Android iOS Linux MacOS Windows
autostart OS起動時の自動起動 - -
barcode-scanner QR/バーコードスキャン - - -
biometric 生体認証 - - -
clipboard-manager クリップボード操作
cli コマンドライン引数解析 - -
deep-link URLハンドラー設定
dialog ネイティブダイアログ
fs ファイルシステムアクセス
geolocation 位置情報 - - -
global-shortcut グローバルショートカット - -
haptics 触覚フィードバック - - -
http HTTPクライアント
localhost ローカルサーバー - -
log ログ出力
nfc NFC操作 - - -
notification デスクトップ通知
opener 外部アプリで開く
os OS情報
persisted-scope スコープ永続化
positioner ウィンドウ位置 - -
process プロセス管理 - -
shell シェル/外部コマンド -
single-instance 単一インスタンス - -
sql SQLデータベース
store キーバリューストア
stronghold 暗号化データベース
updater アップデート機能 - -
upload ファイルアップロード
websocket WebSocket
window-state ウィンドウ状態保存 - -



コミュニティプラグイン

公式プラグイン以外にも、コミュニティによって開発されたサードパーティプラグインが存在する。

プラグインの探し方

コミュニティプラグインは、以下に示す場所で見つけることができる。

  • GitHub
    tauri-plugin タグで検索する。

  • crates.io
    tauri-plugin で検索してRust crateを探す。

  • npm
    @tauri-apps/plugin 以外のスコープ付きパッケージを探す。


インストール方法

コミュニティプラグインは、手動でインストールする必要がある場合が多い。

# Rust crateをインストール
cargo add tauri-plugin-example

# NPMパッケージをインストール
npm install tauri-plugin-example-api


注意事項

コミュニティプラグインを使用する場合は、以下に示す事柄に注意する。

  • セキュリティ
    信頼できる作者のプラグインのみを使用する。
    ソースコードを確認することを推奨する。

  • メンテナンス状況
    最終更新日やIssueの状況を確認する。
    放置されているプラグインは避ける。

  • 互換性
    Tauri v2に対応しているか確認する。
    v1向けのプラグインは動作しない場合がある。



サンプルコード

複数のプラグインを組み合わせたReactアプリケーションの例を示す。

以下の例では、ファイルシステム、ダイアログ、通知プラグインを使用して、テキストエディタの基本機能を定義している。

プラグインのインストール

まず、必要なプラグインをインストールする。

npm run tauri add fs
npm run tauri add dialog
npm run tauri add notification


Reactコンポーネントの定義
 import { useState, useCallback } from 'react';
 import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
 import { open, save, ask } from '@tauri-apps/plugin-dialog';
 import { sendNotification } from '@tauri-apps/plugin-notification';
 
 // テキストエディタコンポーネント
 function TextEditor() {
   const [content, setContent] = useState<string>('');
   const [filePath, setFilePath] = useState<string | null>(null);
   const [isModified, setIsModified] = useState<boolean>(false);
 
   // ファイルを開く処理
   const handleOpen = useCallback(async () => {
     // 保存確認
     if (isModified) {
       const shouldSave = await ask('未保存の変更があります。保存しますか?', {
         title: '確認',
         kind: 'warning'
       });
 
       if (shouldSave) {
         await handleSave();
       }
     }
 
     // ファイル選択ダイアログを表示
     const selectedPath = await open({
       multiple: false,
       filters: [
         { name: 'テキストファイル', extensions: ['txt', 'md'] },
         { name: '全てのファイル', extensions: ['*'] }
       ]
     });
 
     if (selectedPath && typeof selectedPath === 'string') {
       try {
         // ファイルの内容を読み込む
         const text = await readTextFile(selectedPath);
         setContent(text);
         setFilePath(selectedPath);
         setIsModified(false);
 
         // 通知を送信
         await sendNotification({
           title: 'ファイルを開きました',
           body: selectedPath
         });
       }
       catch (error) {
         console.error('ファイルの読み込みに失敗しました:', error);
         await sendNotification({
           title: 'エラー',
           body: 'ファイルの読み込みに失敗しました'
         });
       }
     }
   }, [isModified]);
 
   // ファイルを保存する処理
   const handleSave = useCallback(async () => {
     let targetPath = filePath;
 
     // ファイルパスがない場合は保存ダイアログを表示
     if (!targetPath) {
       targetPath = await save({
         filters: [
           { name: 'テキストファイル', extensions: ['txt'] }
         ],
         defaultPath: 'untitled.txt'
       }) as string | null;
     }
 
     if (targetPath) {
       try {
         // ファイルに書き込む
         await writeTextFile(targetPath, content);
         setFilePath(targetPath);
         setIsModified(false);
 
         await sendNotification({
           title: '保存完了',
           body: targetPath
         });
       }
       catch (error) {
         console.error('ファイルの保存に失敗しました:', error);
         await sendNotification({
           title: 'エラー',
           body: 'ファイルの保存に失敗しました'
         });
       }
     }
   }, [content, filePath]);
 
   // テキスト変更時の処理
   const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
     setContent(e.target.value);
     setIsModified(true);
   };
 
   return (
     <div className="text-editor">
       <div className="toolbar">
         <button onClick={handleOpen}>開く</button>
         <button onClick={handleSave}>保存</button>
         <span>{filePath || '未保存'}</span>
         {isModified && <span>*</span>}
       </div>
       <textarea
         value={content}
         onChange={handleChange}
         placeholder="ここにテキストを入力..."
       />
     </div>
   );
 }
 
 export default TextEditor;


Capabilities設定

このアプリケーションには、以下に示すCapabilities設定が必要である。

 {
   "$schema": "../gen/schemas/desktop-schema.json",
   "identifier": "default",
   "description": "Text Editor Capability",
   "windows": ["main"],
   "permissions": [
     "core:default",
     "fs:default",
     "dialog:default",
     "notification:default"
   ]
 }



トラブルシューティング

プラグインが認識されない場合

プラグインが正しく認識されない場合は、以下に示す項目を確認する。

  • 依存関係の確認
    Cargo.tomlとpackage.jsonの両方に依存関係が追加されているか確認する。

  • 初期化コードの確認
    src-tauri/src/lib.rs ファイルにプラグインの初期化コードが追加されているか確認する。

  • ビルドの実行
    npm run tauri build または npm run tauri dev コマンドを再実行する。


パーミッションエラーが発生する場合

プラグインのAPIを呼び出した時にパーミッションエラーが発生する場合は、Capabilities設定を確認する。

  • エラーメッセージの確認
    コンソールに出力されるエラーメッセージから、必要なパーミッションを特定する。

  • Capabilitiesファイルの確認
    src-tauri/capabilities/default.json ファイルに必要なパーミッションが含まれているか確認する。

  • スコープ設定の確認
    ファイルシステム等、スコープ設定が必要なプラグインの場合は、allow / denyを確認する。


ビルドエラーが発生する場合

ビルド時にエラーが発生する場合は、以下に示す事柄を確認する。

  • Rustバージョンの確認
    rustc --version コマンドを実行して、Rustのバージョンを確認する。
    Tauri v2はRust 1.70以降を必要とする。

  • 依存関係の更新
    cargo update コマンドを実行して、で依存関係を更新する。

  • キャッシュのクリア
    cargo clean コマンドを実行して、でビルドキャッシュをクリアする。



参考リンク