- 技術 💻
Tauriとは|使い方・Electronとの違いをinvokeと権限の実物で解説
結論
Tauri(タウリ)は、画面を HTML・CSS・JavaScript で作り、裏側の処理を Rust で書くデスクトップ・モバイルアプリのフレームワークです。ブラウザーを同梱せず OS の WebView を使うため、Chromium を丸ごと持つ Electron より配布物が小さくなります。
この記事でわかること
- create-tauri-app で作った雛形の全ファイルと、invoke・capabilities の実物
- Electron 45.1.0 本体の実測サイズと、Tauri の配布物に入るものの違い
- 依存不足・ポート衝突・権限不足など、エラーの原文と直し方
Tauri のアプリは、画面を描く WebView と、Rust で書いたコア(本体)の2つでできています。画面から Rust の関数を呼ぶ入口が invoke、どの画面に何を許すかを決めるのが capabilities(権限の設定ファイル)です。
flowchart TD
UI[画面 HTML・CSS・JS<br>OS の WebView で表示] -->|invoke greet| ACL{capabilities で<br>許可されている?}
ACL -->|はい| CORE[Rust のコマンド<br>greet を実行]
ACL -->|いいえ| NG[not allowed で拒否]
CORE -->|戻り値を JSON で返す| UI
CORE --> OS[ファイル・通知・ダイアログ<br>OS の機能]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| Tauri とは | Web 技術の画面+Rust の本体でアプリを作るフレームワーク。MIT・Apache-2.0 | Tauriとは |
| Tauri の読み方 | タウリ(公式の日本語ドキュメントの表記) | Tauriとは |
| Tauri と Electron の違い | Electron は Chromium と Node.js を同梱、Tauri は OS の WebView と Rust | TauriとElectronの違い |
| Tauri の使い方(始め方) | npm create tauri-app@latest → npm install → npm run tauri dev |
create-tauri-appで作る |
| Rust は必須か | ビルドに Rust のツールチェーンは必須。書く量は機能しだい | Tauriの始め方 |
| 画面から Rust を呼ぶ | #[tauri::command] を付けて登録し、invoke("名前", 引数) |
invokeでRustを呼ぶ |
| not allowed と出る | capabilities にプラグインの権限が無い | capabilitiesの設定 |
| スマホアプリも作れるか | v2 から iOS・Android に対応。iOS のビルドは macOS が要る | モバイル対応 |
確認環境:Ubuntu 24.04.5 LTS(x86_64・2 CPU)の上で、Node.js 22.23.4・npm 10.9.9・Rust 1.97.0(cargo 1.97.0・rustup 1.28.2)を使い、作業用のフォルダーで npm create tauri-app@4.7.5(vanilla-ts テンプレート)を実行しました。入った版は @tauri-apps/cli 2.12.4・@tauri-apps/api 2.12.4・Vite 8.3.5・TypeScript 6.0.3、Rust 側は cargo generate-lockfile で解決した tauri 2.12.5・wry 0.57.1・tao 0.37.2 です。CLI の各コマンドと Vite(127.0.0.1 の 1420 番)を実行し、invoke は @tauri-apps/api の mocks を Node.js で動かして確かめました。このマシンは他の作業と共有しており、Tauri 本体のビルドに要る WebKitGTK の開発用パッケージ(96個)を入れず、Rust 側のビルド(tauri dev・tauri build)は行っていません。ビルド前に止まるエラーは、依存の一部(webkit2gtk-sys 2.0.2)だけを実際にビルドして原文を取り、Rust 側のエラー文は tauri 2.12.5 のソースコードの書式から引いています。Electron は 45.1.0 の Linux x64 版の zip を取得して中身を数えました。手順・仕様は Tauri v2 の公式ドキュメントで確かめ、図は mermaid 11.16.0 で描画を確かめています(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Tauriとは|使い方・Electronとの違いをinvokeと権限の実物で解説」
Tauriとは(読み方・できること・ライセンス)
この節では、Tauri が何をするための道具で、どんなアプリに使われるのかが分かります。
Tauri は、Windows・macOS・Linux と iOS・Android 向けのアプリを、Web の技術で作るためのフレームワークです。公式ドキュメントは Tauri を「主要なデスクトップとモバイルのプラットフォーム向けに、小さく速いバイナリを作るフレームワーク」と説明し、OS に入っている WebView を使うため「最小の Tauri アプリは 600KB 未満にできる」と書いています。
- 読み方:タウリ。公式の日本語ドキュメントでもカタカナでこう書かれます。
- 画面:HTML・CSS・JavaScript に変換できるものなら何でもよく、React・Vue・Svelte・Angular・素の TypeScript などを選べます。雛形には Rust で画面を書く Leptos・Yew・Dioxus もあります。
- 本体(コア):Rust。OS の機能(ファイル・通知・ダイアログ・トレイ)を呼ぶ処理や重い計算を書きます。モバイルでは Swift・Kotlin でプラグインを書けます。
- ライセンス:MIT と Apache-2.0 のデュアルライセンス。商用のアプリにも使えます。
- 運営:オランダの非営利団体 The Commons Conservancy の中の「Tauri Programme」(create-tauri-app のヘルプにも表示)。
版は2026年10月29日時点の npm view @tauri-apps/cli dist-tags の値です。2.12.0(9月26日)から 2.12.4(10月21日)まで修正版が続いています。3.0 は alpha(試作段階)です。
Tauriの仕組み(WebView・Rust・IPC)
この節では、Tauri のアプリが中でどう動いているか、OS ごとに何が違うかが分かります。
Tauri のアプリは、画面を描く WebView のプロセスと、Rust で書いたコアのプロセスに分かれ、その間を IPC(プロセス間通信)でやり取りします。画面の JavaScript は OS の機能に直接触れず、Rust 側に「この処理をして」と頼みます。その頼み方が invoke で、頼んでよい範囲を決めるのが capabilities です。
WebView は、OS ごとに次のものが使われます(Tauri 公式「Webview Versions」より)。
| OS | 使われる WebView | 描画エンジン | 更新のされ方 |
|---|---|---|---|
| Windows | WebView2 | Chromium(Edge) | WebView2 が自動で更新される。Windows 11 には最初から入っている |
| macOS・iOS | WKWebView | WebKit(Safari) | OS のアップデートで更新。サポートが終わった OS は更新されない |
| Linux | WebKitGTK(webkit2gtk) | WebKit | ディストリビューションのパッケージで更新。版は配布元しだい |
| Android | Android System WebView | Chromium | 端末で選ばれている WebView による |
OS の WebView を使う利点
ブラウザーを同梱しないので配布物が小さい
WebView のセキュリティ修正は OS 側で入る
複数の Tauri アプリで同じ WebView を共有する
OS の WebView を使う注意
Windows は Chromium、Mac・Linux は WebKit で描画が違う
サポートが終わった macOS では新しい Web API が使えない
3つの OS で表示を確かめる手間が増える
Tauri のコアは、ウィンドウを作る tao と、WebView を包む wry という2つの Rust のライブラリの上にできています。手元で依存を解決すると、tauri 2.12.5 の下に wry 0.57.1・tao 0.37.2・webkit2gtk 2.0.2(Linux 用)が入りました。
TauriとElectronの違い(サイズを実測)
この節では、Tauri と Electron の違いと、配布物の大きさが何で決まるのかが、実測の数字で分かります。
違いの根本は「ブラウザーを同梱するかどうか」です。Electron はアプリごとに Chromium と Node.js を持ち、Tauri は OS の WebView を借りて、本体を Rust で書きます。
| 比べる点 | Tauri 2.12 | Electron 45.1.0 |
|---|---|---|
| 画面の描画 | OS の WebView(WebView2・WKWebView・WebKitGTK) | 同梱の Chromium(全 OS で同じ版) |
| 本体(裏側)の言語 | Rust(モバイルのプラグインは Swift・Kotlin も) | JavaScript(Node.js) |
| OS の機能を使う許可 | capabilities で、ウィンドウごとに許可した権限だけ | preload と contextBridge で、自分で公開する関数を決める |
| npm のパッケージ | 画面側では使える。本体側では Node.js の API は使えない | 本体(メインプロセス)でもそのまま使える |
| モバイル | iOS・Android に対応(v2 から) | 対象外 |
配布物の大きさの実測
Electron は 45.1.0 の Linux x64 版の本体(GitHub Releases の zip)を取得し、unzip -l で中身を数えました。Tauri は同じ環境で雛形の画面を vite build した大きさと、Linux で WebView として使われる OS 側のパッケージの大きさを apt-cache show で見ました。
$ ls -l electron.zip
-rw-r--r-- 1 root root 123917468 Oct 30 21:14 electron.zip
$ unzip -l electron.zip | tail -1
286773955 72 files
$ unzip -l electron.zip | sort -k1 -n -r | head -5
286773955 72 files
234458440 1980-01-01 00:00 electron
13572592 1980-01-01 00:00 resources.pak
10824432 1980-01-01 00:00 icudtl.dat
5598206 1980-01-01 00:00 LICENSES.chromium.html
$ npm run build
dist/index.html 8.31 kB │ gzip: 3.51 kB
dist/assets/index-0Y_Rzos9.css 1.40 kB │ gzip: 0.65 kB
dist/assets/index-BX7T4ELo.js 1.05 kB │ gzip: 0.56 kB
$ du -ab dist | tail -1
10771 dist
Electron は、画面が 10.8KB でも、配る物には 286.8MB の Chromium と Node.js が付きます。Tauri の配る物は、Rust のバイナリ(画面のファイルを中に埋め込む)とインストーラーだけです。この環境では Rust 側をビルドしていないため、Tauri のバイナリの大きさは公式の「600KB 未満にできる」という記載にとどめます。
ただし、Tauri の WebView が「無料」なわけではありません。Linux では OS 側に WebKitGTK が要り、Ubuntu 24.04 のパッケージの大きさは次のとおりでした。
| OS 側のパッケージ(Ubuntu 24.04) | 版 | 入れたあとの大きさ |
|---|---|---|
| libwebkit2gtk-4.1-0(WebView の本体) | 2.52.6 | 93,416KB |
| libjavascriptcoregtk-4.1-0(JavaScript エンジン) | 2.52.6 | 31,624KB |
| 公式の前提パッケージ一式(開発用) | ― | 新しく96個・ダウンロード 53.9MB |
この約125MB は OS に1回入れれば、すべての Tauri アプリ(と他の GTK アプリ)で共有されます。Windows 11 の WebView2、macOS の WKWebView も最初から OS に入っています。「アプリごとに持つか、OS のものを共有するか」が、サイズの差の正体です。
メモリ使用量の考え方
メモリはこの環境では測っていません(WebKitGTK を入れていないため)。測るときは、Tauri は本体と WebView 側のプロセス(Linux なら WebKitWebProcess・WebKitNetworkProcess)、Electron はメインと複数の Helper を全部足して、同じ時点(起動から何秒後か)で比べます。本体のプロセスだけを見ると Tauri が極端に小さく見えます。
Electron 側の仕組み・安全な IPC・パッケージ化は、関連記事「Electronとは|使い方・仕組み・安全なIPC・パッケージ化を実例で解説」で扱っています。
Tauriの始め方(必要なものとインストール)
この節では、Tauri を使い始める前に、OS ごとに何を入れるのかが分かります。
どの OS でも Rust(rustup)が必須で、画面を JavaScript のフレームワークで作るなら Node.js も入れます。そのうえで、OS ごとに WebView とビルドの道具を用意します(Tauri 公式「Prerequisites」より)。
OS ごとの前提を入れる
Windows は Microsoft C++ Build Tools(「C++ によるデスクトップ開発」)と WebView2(Windows 10 の 1803 以降と Windows 11 は入っている)。macOS は Xcode か xcode-select --install。Linux(Debian・Ubuntu)は下の apt の一式。
Rust を rustup で入れる
公式の手順は curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh。Windows では既定のツールチェーンを MSVC にする。
Node.js(LTS)を入れる
画面を Vite・React などで作る場合だけ要る。pnpm・yarn は corepack enable で使える。
tauri info で足りないものを確かめる
雛形を作ったあと npm run tauri info を実行すると、WebView・Rust・Node.js の有無と版が一覧で出る。
Linux(Debian・Ubuntu)の前提パッケージは、公式ドキュメントでは次の1行です。
sudo apt update
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev
この環境で tauri info を実行すると、WebKitGTK と rsvg2 が無いことがはっきり表示されました。
[✘] Environment
- OS: Ubuntu 24.4.0 x86_64 (X64) (Unknown DE on Unknown Session)
✘ webkit2gtk-4.1: not installed
Visit https://v2.tauri.app/start/prerequisites/ to learn more about tauri prerequisites
✘ rsvg2: not installed
Visit https://v2.tauri.app/start/prerequisites/ to learn more about tauri prerequisites
✔ rustc: 1.97.0 (2d8144b78 2026-07-07)
✔ cargo: 1.97.0 (c980f4866 2026-06-30)
✔ rustup: 1.28.2 (e4f3ad6f8 2025-04-28)
✔ Rust toolchain: stable-x86_64-unknown-linux-gnu (default)
- node: 22.23.4
- npm: 10.9.9
[-] Packages
- tauri 🦀: 2
- @tauri-apps/api ⱼₛ: 2.12.4
- @tauri-apps/cli ⱼₛ: 2.12.4
[-] App
- build-type: bundle
- CSP: unset
- frontendDist: ../dist
- devUrl: http://localhost:1420/
- bundler: Vite
Rust は必須ですが、たくさん書く必要があるとは限りません。ファイル・ダイアログ・通知・HTTP などは公式プラグインに JavaScript の API があり、Rust 側は「プラグインを登録する1行」で済みます。自分で OS の処理や重い計算を書くときに、所有権・借用などの Rust の基本が要ります。
create-tauri-appでプロジェクトを作る(Tauriの使い方)
この節では、Tauri のプロジェクトを1つ作り、何ができあがるのかが分かります。
雛形は npm create tauri-app@latest で作ります。対話で名前・識別子・言語・パッケージマネージャー・画面のテンプレートを聞かれます。CI などで対話を飛ばすときは、オプションで全部渡せます。ヘルプの一部です。
$ npm create tauri-app@4.7.5 -- --help
Tauri Programme within The Commons Conservancy
Rapidly scaffold out a new tauri app project.
OPTIONS:
-m, --manager <MANAGER> Specify preferred package manager [cargo, pnpm, yarn, npm, deno, bun, dotnet]
-t, --template <TEMPLATE> Specify the UI template to use [vanilla, vanilla-ts, vue, vue-ts, svelte, svelte-ts, react, react-ts, solid, solid-ts, yew, leptos, sycamore, angular, preact, preact-ts, blazor, dioxus]
--identifier <identifier> Specify a unique identifier for your application
-y, --yes Skip prompts and use defaults where applicable
--tauri-version [1 | 2] Bootstrap a project using the provided Tauri version. Defaults to the latest stable release.
TypeScript だけの雛形(vanilla-ts)で作りました。
$ npm create tauri-app@4.7.5 -- hello-tauri --template vanilla-ts --manager npm --identifier com.example.hellotauri -y
Template created!
Your system is missing dependencies (or they do not exist in $PATH):
╭────────────────────┬─────────────────────────────────────────────────────╮
│ webkit2gtk & rsvg2 │ Visit https://tauri.app/guides/prerequisites/#linux │
╰────────────────────┴─────────────────────────────────────────────────────╯
Make sure you have installed the prerequisites for your OS: https://tauri.app/start/prerequisites/, then run:
cd hello-tauri
npm install
npm run tauri android init
For Desktop development, run:
npm run tauri dev
雛形の作成は1秒台で終わり、大きさは 308KB でした。npm install は20パッケージ・9秒で、node_modules は 79MB(そのうち Tauri CLI の Linux 用バイナリが 19MB)でした。
画面を React で作る場合の Vite の基本は、関連記事「React環境構築をViteで行う手順|create viteの使い方」で扱っています。テンプレートを react-ts にすると、同じ構成の上に React が載ります。
生成されたファイルの読み方(tauri.conf.json・Cargo.toml)
この節では、雛形のどのファイルが何をしているのか、どこを書き換えるのかが分かります。
画面は src/、Rust の本体と設定は src-tauri/ に分かれます。できたファイルは次のとおりです(アイコン16個は省略)。
hello-tauri/
├── index.html 画面の HTML(入力欄と Greet ボタン)
├── package.json npm の設定。scripts に "tauri": "tauri"
├── vite.config.ts Vite の設定(ポート 1420 固定)
├── src/
│ ├── main.ts invoke("greet") を呼ぶ
│ └── styles.css
└── src-tauri/
├── Cargo.toml Rust の依存と release の最適化
├── build.rs tauri_build::build()
├── tauri.conf.json アプリ名・識別子・ウィンドウ・ビルド設定
├── capabilities/
│ └── default.json main ウィンドウに許す権限
├── icons/ 各 OS 用のアイコン
└── src/
├── main.rs lib の run() を呼ぶだけ
└── lib.rs コマンドの定義と登録
tauri.conf.json(アプリの設定)
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "hello-tauri",
"version": "0.1.0",
"identifier": "com.example.hellotauri",
"build": {
"beforeDevCommand": "npm run dev",
"devUrl": "http://localhost:1420",
"beforeBuildCommand": "npm run build",
"frontendDist": "../dist"
},
"app": {
"withGlobalTauri": true,
"windows": [
{ "title": "hello-tauri", "width": 800, "height": 600 }
],
"security": { "csp": null }
},
"bundle": { "active": true, "targets": "all", "icon": ["icons/32x32.png", "..."] }
}
| 項目 | 意味 | 書き換える場面 |
|---|---|---|
identifier |
アプリを見分ける ID(逆ドメイン形式) | 配布前に必ず自分のものへ。設定の保存場所にも使われる |
build.devUrl |
tauri dev で WebView が開く URL |
Vite 以外の開発サーバーを使うとき |
build.frontendDist |
tauri build で埋め込む画面のフォルダー |
出力先が dist 以外のとき |
app.withGlobalTauri |
window.__TAURI__ に API を載せる |
import を使うなら false でよい |
app.security.csp |
WebView に付ける Content-Security-Policy | 雛形は null(未設定)。配布前に設定する |
雛形の CSP は null で、tauri info にも「CSP: unset」と出ます。外部のスクリプトを読み込まない画面なら、配布前に CSP を設定します。CSP の書き方そのものは、関連記事「CSP設定(Content-Security-Policy)|nginx段階導入」で扱っています。
Cargo.toml(Rust の依存と最適化)
[lib]
name = "hello_tauri_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
[profile.release]
codegen-units = 1
lto = true
opt-level = 3
panic = "abort"
strip = true
release の設定は、雛形の時点で最適化が入っています。公式の「App Size」のページは opt-level = "s"(大きさを優先)を勧めており、雛形の 3(速さを優先)とは違います。配布物を小さくしたいなら "s" か "z" に変えます。
依存の数は cargo generate-lockfile で見ました。「Locking 448 packages」と出て、Cargo.lock には 449 個(自分を含む)が並びました。全 OS 分を含む数で、ビルドされるのは自分の OS の分だけですが、最初のビルドが長い理由はこの数です。
tauri dev・tauri buildの使い方と出力
この節では、開発中にアプリを動かすコマンドと、配布物を作るコマンドの違いが分かります。
npm run tauri dev は開発用の起動、npm run tauri build は配布用のビルドです。どちらも、先に tauri.conf.json の beforeDevCommand・beforeBuildCommand(ここでは Vite)を実行し、そのあと Rust をビルドします。
| コマンド | 画面の扱い | Rust のビルド | できるもの |
|---|---|---|---|
tauri dev |
Vite の開発サーバー(localhost:1420)を WebView で開く。保存すると即反映 | debug。Rust を変えると再ビルドして再起動 | 動いているアプリ(配布物は作らない) |
tauri build |
npm run build の dist をバイナリに埋め込む |
release(Cargo.toml の profile) | 実行ファイルとインストーラー |
tauri build --debug |
dist を埋め込む | debug | 開発者ツールが開けるビルド |
tauri build --no-bundle |
dist を埋め込む | release | 実行ファイルだけ(インストーラーは作らない) |
Linux の tauri build --help では、作れる形式は次の3つでした。
-b, --bundles [<BUNDLES>...]
Space or comma separated list of bundles to package
[possible values: deb, rpm, appimage]
Windows では msi・NSIS(exe)、macOS では app・dmg が作られます(公式ドキュメントより)。インストーラーは各 OS の上でビルドするのが基本で、3つの OS 分は GitHub Actions などの OS ごとのランナーで作ります。
画面だけを先に動かす
tauri dev が最初に動かす Vite だけを実行すると、次のようになりました。ブラウザーで http://localhost:1420/ を開くと、雛形の画面(title は「Tauri App」)が返りました。
$ npm run dev
> hello-tauri@0.1.0 dev
> vite
VITE v8.3.5 ready in 184 ms
➜ Local: http://localhost:1420/
普通のブラウザーで開いた画面では invoke が失敗します(次の節で原文を示します)。見た目はブラウザー、OS の機能は tauri dev で確かめると分けると速く進みます。
Tauri CLI のサブコマンド
dev・build
開発用の起動と、配布物のビルド。bundle はビルド済みのものからインストーラーだけ作る。
いちばん使う2つ
info
OS・WebView・Rust・Node.js・Tauri の版を一覧にする。困ったときの最初の1手。
質問するときに貼る
add・remove
公式プラグインを Cargo と npm の両方に入れ、lib.rs に登録の1行を足す。
権限は別に確かめる
capability・permission
capabilities のファイルを作り、権限を足す。icon はアイコン一式、signer は自動更新の署名鍵。
android・migrate もある
Linux の tauri --help の一覧には android はありましたが、ios はありませんでした。iOS のビルドは macOS でしかできないためです。
invokeでRustのコマンドを呼ぶ(Tauriの使い方の芯)
この節では、画面の JavaScript から Rust の関数を呼ぶ書き方と、引数・戻り値・エラーの決まりが分かります。
Rust の関数に #[tauri::command] を付け、generate_handler! で登録し、画面から invoke("関数名", 引数) で呼びます。雛形の lib.rs がいちばん小さな例です。
// src-tauri/src/lib.rs(雛形のまま)
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_opener::init())
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
// src/main.ts(雛形のまま・一部)
import { invoke } from "@tauri-apps/api/core";
async function greet() {
if (greetMsgEl && greetInputEl) {
greetMsgEl.textContent = await invoke("greet", {
name: greetInputEl.value,
});
}
}
@tauri-apps/api 2.12.4 の invoke の中身は、window.__TAURI_INTERNALS__.invoke(cmd, args, options) を呼ぶだけの1行でした。つまり、Tauri の WebView の外(普通のブラウザーや Node.js)では、__TAURI_INTERNALS__ が無いので失敗します。公式の mocks(テスト用の差し替え)を Node.js で動かし、Rust 側に何が届くかと、外で呼んだときのエラーを確かめました。
// ipc-test.mjs(Node.js 22 で実行)
globalThis.window = globalThis;
const { invoke, isTauri } = await import("@tauri-apps/api/core");
const { mockIPC, clearMocks } = await import("@tauri-apps/api/mocks");
console.log("isTauri():", isTauri());
try { await invoke("greet", { name: "RJC" }); } catch (e) { console.log("Tauri の外で invoke:", String(e)); }
mockIPC((cmd, args) => {
console.log("Rust 側に届く名前と引数:", cmd, JSON.stringify(args));
if (cmd === "greet") return `Hello, ${args.name}! You've been greeted from Rust!`;
throw new Error(`Command ${cmd} not found`);
});
console.log("戻り値:", await invoke("greet", { name: "RJC" }));
clearMocks();
isTauri(): false
Tauri の外で invoke: TypeError: Cannot read properties of undefined (reading 'invoke')
Rust 側に届く名前と引数: greet {"name":"RJC"}
戻り値: Hello, RJC! You've been greeted from Rust!
isTauri() で Tauri の中かどうかを判定できるので、ブラウザーでも開く画面では、外のときは invoke を呼ばない分岐を入れます。mocks は、画面の単体テストで Rust を動かさずに invoke を差し替える用途にも使えます。
引数・戻り値・エラーの決まり
| 決まり | 内容 | 守らないと |
|---|---|---|
| 引数名は camelCase | Rust の invoke_message は JS から invokeMessage で渡す。snake_case のままにするなら #[tauri::command(rename_all = "snake_case")] |
command ... missing required key ... |
| 戻り値は Serialize できる型 | エラーの型も含めて serde::Serialize が要る。map_err(|e| e.to_string()) で文字列にするのが手軽 |
コンパイルが通らない |
| Err を返すと Promise が reject | JS 側は try・catch で受ける |
画面にエラーが出ず止まって見える |
| lib.rs のコマンドに pub を付けない | 別のモジュールに置くなら pub にし、commands::名前 で登録 |
コード生成の都合でコンパイルエラー |
| async のコマンドで借用の引数を使わない | &str は String にする。State を使うなら戻り値を Result にする |
コンパイルエラー |
エラーを返すコマンドは、公式ドキュメントの書き方に沿うと次の形になります(この環境では Rust 側をビルドしていないため、書き方の例として示します)。
#[tauri::command]
fn read_note(path: String) -> Result<String, String> {
std::fs::read_to_string(&path).map_err(|e| e.to_string())
}
// 登録は generate_handler! の1か所にまとめて並べる
.invoke_handler(tauri::generate_handler![greet, read_note])
try {
const text = await invoke<string>("read_note", { path: "/tmp/a.txt" });
} catch (e) {
console.error("Rust から返ったエラー:", e); // Err の文字列がそのまま入る
}
Rust 側で何が返るかは、tauri 2.12.5 のソースにある文言で分かります。登録していない名前を呼ぶと Command gret not found、必須の引数が無いと command greet missing required key name で reject されます(gret・greet・name の部分が呼んだ名前に変わります)。大きなデータを順に送るときは、公式が勧める Channel(tauri::ipc::Channel)を使います。
capabilities(権限)の設定
この節では、Tauri の権限の仕組みと、プラグインの機能を使うときに何を書くのかが分かります。
capabilities は「どのウィンドウ(WebView)に、どの権限を与えるか」を書く JSON(か TOML)のファイルで、src-tauri/capabilities/ に置きます。v1 の allowlist に代わって v2 で入った仕組みです。雛形の default.json は次のとおりです。
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:default",
"opener:default"
]
}
| キー | 意味 |
|---|---|
identifier |
capability の名前。tauri.conf.json の app.security.capabilities で名前を並べると、並べたものだけが有効になる(書かなければフォルダー内の全部が有効) |
windows |
対象のウィンドウのラベル(タイトルではない)。"*" で全部 |
permissions |
許す権限。プラグイン名:権限名 の形 |
platforms |
["linux", "macOS", "windows"] などで OS を絞る |
remote |
外部の URL を開いたページに権限を与えるとき(urls で絞る) |
権限の中身を確かめる
opener:default が何を許すかは、プラグインの定義(tauri-plugin-opener 2.7.2 の permissions/default.toml)に書かれています。
[default]
description = """This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application
as well as reveal file in directories using default file explorer"""
permissions = [
"allow-open-url",
"allow-reveal-item-in-dir",
"allow-default-urls",
]
default は「よく使うものの詰め合わせ」で、全部を許すわけではありません。たとえば core:default に含まれる core:window:default は、ウィンドウの大きさや状態を読む権限が中心で、tauri 2.12.5 の定義ではタイトルを変える core:window:allow-set-title は含まれていませんでした。画面から setTitle() を呼ぶなら、その権限を足します。
CLI で capability を作る
設定画面用のウィンドウ(ラベル settings)だけにタイトル変更を許す capability を、CLI で作りました。
$ npx tauri capability new settings --description "設定ウィンドウだけに許可" --windows settings --permission core:default --permission core:window:allow-set-title
Created capability at /dev/shm/t131/hello-tauri/src-tauri/capabilities/settings.json
{
"identifier": "settings",
"description": "設定ウィンドウだけに許可",
"local": true,
"windows": [
"settings"
],
"permissions": [
"core:default",
"core:window:allow-set-title"
]
}
--permission にカンマ区切りで2つ渡すと、次のエラーになりました。権限は1つずつ --permission を繰り返して渡します。
invalid permission `core:default,core:window:allow-set-title`: identifiers can only include lowercase ASCII, hyphens which are not leading or trailing, and a single colon if using a prefix
capabilities で守れるもの・守れないもの
全ウィンドウに強い権限をまとめて渡す
"windows": ["*"] に fs やシェルの権限を全部入れる。外部のページを開くウィンドウにも同じ権限が付く境界はウィンドウのラベル単位で決まる
自分のコマンドは capabilities で守られていると思い込む
generate_handler! に登録した自分のコマンドを、どのウィンドウからでも呼べる状態のまま、危ない処理を書く公式も「Rust のコードの誤りや緩いスコープは防げない」と書いている
公式ドキュメントは、Linux と Android では埋め込んだ iframe からの要求とウィンドウ自身の要求を区別できない、とも書いています。外部のページを iframe で読み込む画面には、強い権限を持つウィンドウを使わないようにします。
プラグインの追加(tauri add)と権限の足し方
この節では、ダイアログ・ファイル・通知などの公式プラグインを追加する手順と、追加したあとに忘れやすい権限の設定が分かります。
公式プラグインは npm run tauri add 名前 で入れます。ファイルを開くダイアログ(dialog)を足したときの出力です。
$ npx tauri add dialog
Info Installing Cargo dependency "tauri-plugin-dialog"...
Info Installing NPM dependency "@tauri-apps/plugin-dialog@~2"...
Info Adding plugin to /dev/shm/t131/hello-tauri/src-tauri/src/lib.rs
Info Running `cargo fmt`...
3秒ほどで、Cargo.toml に tauri-plugin-dialog = "2"、package.json に @tauri-apps/plugin-dialog(2.8.4)、lib.rs に .plugin(tauri_plugin_dialog::init()) の1行が入りました。一方、この環境(capabilities のファイルが2つある状態)では、capabilities には何も足されませんでした。権限が無いままダイアログを開こうとすると拒否されるので、tauri permission add で足します。
$ npx tauri permission add dialog:default
failed to prompt multi-select: IO error: not a terminal
Error failed to prompt multi-select: IO error: not a terminal
$ npx tauri permission add dialog:default default
Added permission `dialog:default` to `default` at /dev/shm/t131/hello-tauri/src-tauri/capabilities/default.json
capability が複数あると「どれに足すか」を対話で聞かれるため、端末の無い CI やスクリプトでは失敗します。2つ目の引数で capability の名前(ここでは default)を渡すと、確認なしで足されました。足したあとの default.json は次のとおりです。
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": [
"main"
],
"permissions": [
"core:default",
"opener:default",
"dialog:default"
]
}
dialog の default は、プラグインの定義(tauri-plugin-dialog 2.8.4)では allow-message・allow-save・allow-open の3つでした。ファイルを開くだけなら dialog:allow-open だけを足す方が、許す範囲が狭くなります。
1add は3か所を変える
Cargo.toml・package.json・lib.rs。差分を見て、入った版と登録の行を確かめる。
2権限は別に確かめる
capabilities に足されたかを必ず見る。無ければ tauri permission add。
3default より狭く
使う操作だけを許す。removeUnusedCommands と組み合わせると、使わないコマンドをビルドから外せる。
build.removeUnusedCommands(tauri.conf.json)は tauri 2.4 以降の設定で、実行中に権限を足す作りには使えません。
Tauriのモバイル対応(Android・iOS)
この節では、Tauri で iOS・Android のアプリを作るときに要るものと、できることの範囲が分かります。
Tauri v2 は、同じプロジェクトから iOS・Android のアプリも作れます。雛形の作成時にも npm run tauri android init と npm run tauri android dev が案内されました。モバイルの前提は次のとおりです(公式「Prerequisites」より。この環境では動かしていません)。
| 対象 | 要るもの | Rust のターゲット |
|---|---|---|
| Android | Android Studio、SDK・NDK・Build-Tools、JAVA_HOME・ANDROID_HOME・NDK_HOME | rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android |
| iOS | macOS 上の Xcode(Command Line Tools だけでは不可)、CocoaPods | rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim |
モバイルの OS 固有の機能は、Swift・Kotlin で書いたプラグインから使います。公式プラグインには、通知・バーコード読み取り・生体認証・NFC など、モバイル向けのものもあります。モバイルが主役のアプリなら、部品の厚さで Flutter・React Native も比べます。Flutter の始め方は、関連記事「Flutterとは|始め方・インストールとDartの基本を図と実例で解説」で扱っています。
Tauriのよくあるエラーと直し方
この節では、Tauri を使い始めたときに出やすいエラーの原文と、それぞれの直し方が分かります。
まず npm run tauri info で環境を確かめ、次にエラーが「ビルドの前」「起動の前」「invoke のとき」のどこで出たかを見ます。
Linux で WebKitGTK が無い(ビルドが止まる)
前提のパッケージを入れずに Rust 側をビルドすると、GTK・WebKitGTK を探す依存(*-sys)のビルドで止まります。Tauri と同じ webkit2gtk-sys 2.0.2 だけを依存にした小さなプロジェクトで、cargo build を実行した原文です(15秒ほどで止まりました)。
Compiling gdk-sys v0.18.2
error: failed to run custom build command for `gdk-sys v0.18.2`
Caused by:
process didn't exit successfully: `.../build/gdk-sys-4d66658b4a78b04f/build-script-build` (exit status: 1)
--- stderr
pkg-config exited with status code 1
> PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 pkg-config --libs --cflags gdk-3.0 'gdk-3.0 >= 3.22'
pkg-config output:
Package gdk-3.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gdk-3.0.pc'
to the PKG_CONFIG_PATH environment variable
Package 'gdk-3.0', required by 'virtual:world', not found
The system library `gdk-3.0` required by crate `gdk-sys` was not found.
The file `gdk-3.0.pc` needs to be installed and the PKG_CONFIG_PATH environment variable must contain its parent directory.
The PKG_CONFIG_PATH environment variable is not set.
並列のビルドでは、同じ原因で atk-sys が先に止まり The system library `atk` required by crate `atk-sys` was not found. と出ることもありました。どれも「開発用のパッケージ(.pc ファイル)が無い」という意味で、公式の apt の1行(libwebkit2gtk-4.1-dev など)を入れると解消します。
エラーの原文と直し方の一覧
| 出たエラー(原文) | 原因 | 直し方 |
|---|---|---|
✘ webkit2gtk-4.1: not installed(tauri info) |
Linux の前提パッケージが無い | 公式の apt の1行を入れる |
The system library `gdk-3.0` required by crate `gdk-sys` was not found. |
GTK の開発用パッケージが無い | 同上。入れたのに出るなら PKG_CONFIG_PATH を確かめる |
Error: Port 1420 is already in use |
前の tauri dev や別のサーバーが 1420 番を使っている(strictPort) |
使っているプロセスを止める。ポートを変えるなら vite.config.ts と devUrl を両方変える |
TypeError: Cannot read properties of undefined (reading 'invoke') |
普通のブラウザーで画面を開き、Tauri の外で invoke した | tauri dev の窓で動かす。isTauri() で分岐する |
Command gret not found |
invoke の名前違い、または generate_handler! に登録していない | 名前を合わせ、登録を1か所にまとめる |
command greet missing required key name |
引数のキー名が違う(snake_case で渡した等) | JS 側は camelCase で渡す |
dialog.open not allowed. Permissions associated with this command: dialog:allow-open, dialog:default |
capabilities にプラグインの権限が無い | 表示された権限のどれかを capabilities に足す |
failed to prompt multi-select: IO error: not a terminal |
capability が複数あり、端末の無い所で対話になった | tauri permission add 権限 capability名 |
表の not allowed の行は、tauri 2.12.5 のソース(ipc/authority.rs)の書式「{プラグイン}.{コマンド} not allowed. Permissions associated with this command: {権限}」に、tauri-plugin-dialog 2.8.4 の権限の定義を当てはめた形です。Command ... not found と missing required key も同じソースの文言です。この3つは画面を出せない環境のため、実行ではなくソースで確かめています。
Tauri・Electron・Flutter・Wailsの判断表
この節では、デスクトップアプリの作り方を、何を基準に選ぶかが分かります。
「配布物の小ささ・権限を絞る仕組み」を重く見るなら Tauri、「全 OS で同じ描画・npm の資産」を重く見るなら Electron です。Wails は Go と OS の WebView、Flutter は自前の描画エンジンで、言語と得意分野が違います。
| こんなとき | Tauri | Electron | Flutter | Wails |
|---|---|---|---|---|
| 配布物を小さくしたい | ◎ OS の WebView | △ Chromium 同梱 | ○ | ◎ OS の WebView |
| 全 OS で描画をそろえたい | △ OS ごとに違う | ◎ 同じ Chromium | ◎ 自前で描画 | △ OS ごとに違う |
| 既存の Web 画面を使い回す | ◎ | ◎ | × Dart で書き直し | ◎ |
| 裏側を Node.js のパッケージで書きたい | × Rust で書く | ◎ | × | × Go で書く |
| スマホも同じコードで出したい | ○ v2 で対応 | × 対象外 | ◎ 主な用途 | × デスクトップのみ |
| OS の機能の許可を細かく絞りたい | ◎ capabilities | ○ preload で自分で絞る | ○ | ○ |
| チームの得意な言語 | Rust | JavaScript | Dart | Go |
動いている Electron のアプリを軽さだけの理由で移すと、Node.js に頼った部分の書き直しと WebKit での表示確認がまとめて発生します。新しい小さな道具から試すのが手戻りの少ない順です。
配布前のチェック
- 1identifier を自分のものにしたcom.example のままにしない。設定の保存場所にも使われる
- 2CSP を設定した雛形は null。tauri info の CSP が unset のままになっていないか
- 3capabilities を使う分だけにしたdefault の詰め合わせより狭い権限で足りないか。windows のラベルは正しいか
- 43つの OS で表示を確かめたWebView2(Chromium)と WebKit で崩れが無いか
- 5署名と自動更新を用意したWindows のコード署名、macOS の公証(Notarization)、updater の鍵
よくある質問
Q. Tauri の読み方は? A. 「タウリ」です。公式の日本語ドキュメントもこの表記です。
Q. Tauri と Electron の違いは何ですか? A. Electron は Chromium と Node.js をアプリに同梱し、Tauri は OS の WebView を使って裏側を Rust で書きます。手元では Electron 45.1.0 の本体だけで zip 123.9MB・展開後 286.8MB、Tauri は公式で最小 600KB 未満とされています。描画を全 OS でそろえたいなら Electron が有利です。
Q. Rust を知らなくても使えますか? A. ビルドに Rust のツールチェーンは必須ですが、公式プラグインで足りる機能なら Rust はプラグインを登録する1行程度です。自作のコマンドを書くと、所有権・借用・Result などの基本が要ります。
Q. 無料で商用利用できますか? A. MIT と Apache-2.0 のデュアルライセンスで、商用のアプリにも使えます。依存するライブラリのライセンスも合わせて確かめます。
Q. React や Vue と一緒に使えますか? A. 使えます。create-tauri-app で react-ts・vue-ts・svelte-ts などを選べます。Next.js のように Node.js のサーバーが要る機能は使えないため、静的に書き出す設定にします。
Q. invoke が undefined のエラーになります。
A. 普通のブラウザーで画面を開いていると、Cannot read properties of undefined (reading 'invoke') になります。npm run tauri dev で開いた窓で動かすか、isTauri() で Tauri の外では呼ばないようにします。
Q. not allowed と出て、ファイルやダイアログが使えません。
A. capabilities にそのプラグインの権限がありません。エラーに「Permissions associated with this command」として権限名が出るので、そのどれかを src-tauri/capabilities/ の JSON に足します。
Q. 最初のビルドが遅いのはなぜですか? A. 依存のクレート(Rust のライブラリ)が多いためです。雛形で 448 個が解決されました。2回目からは変わった所だけがビルドされます。CI では Rust のビルドの結果をキャッシュします。
Q. Tauri 3.0 を使うべきですか? A. 2026年10月29日時点で 3.0 は alpha(npm の next タグが 3.0.0-alpha.5)です。本番のアプリは 2.x(latest は 2.12.4)で作り、3.0 は公式の移行ガイドと安定版の発表を待って判断します。
Q. Tauri v1 のコードは動きますか?
A. v2 では allowlist が capabilities に変わるなど、設定と API が変わっています。tauri migrate コマンドと公式の移行ガイドで移します。
まとめ
この節では、記事の要点を5つにまとめて振り返れます。
- Tauri は、Web の画面と Rust の本体でアプリを作るフレームワーク。OS の WebView を使い、Windows・macOS・Linux と iOS・Android に対応します。
- Electron との差は「ブラウザーを同梱するか」。Electron 45.1.0 の本体は展開後 286.8MB、Tauri は OS 側の WebView(Linux なら約125MB)を全アプリで共有します。
- 使い方の芯は invoke。
#[tauri::command]を付けて登録し、JS から camelCase の引数で呼び、Err は catch で受けます。 - capabilities は、ウィンドウごとに権限を許す仕組み。プラグインを足したら権限も足し、default より狭くできないかを考えます。
- 困ったら
tauri info。Linux の WebKitGTK 不足、ポート 1420 の衝突、名前・引数・権限の違いが、よくあるつまずきです。
npm の scripts や package.json の書き方は、関連記事「npm コマンド 一覧|package.json 書き方と実行結果・npm 12対応」で扱っています。
参考・出典
確認日はいずれも 2026年10月29日です。
- Tauri「What is Tauri?」:https://v2.tauri.app/start/
- Tauri「Prerequisites」:https://v2.tauri.app/start/prerequisites/
- Tauri「Calling Rust from the Frontend」:https://v2.tauri.app/develop/calling-rust/
- Tauri「Capabilities」:https://v2.tauri.app/security/capabilities/
- Tauri「App Size」:https://v2.tauri.app/concept/size/
- Tauri「Webview Versions」:https://v2.tauri.app/reference/webview-versions/
- Tauri「Tauri 2.0 Stable Release」:https://v2.tauri.app/blog/tauri-20/
- Tauri のソースコード(tauri 2.12.5・tauri-plugin-opener 2.7.2・tauri-plugin-dialog 2.8.4):https://crates.io/crates/tauri
- npm「@tauri-apps/cli」:https://www.npmjs.com/package/@tauri-apps/cli
- Electron Releases(v45.1.0):https://github.com/electron/electron/releases
- Wails「Introduction」:https://wails.io/docs/introduction
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Tauriとは|使い方・Electronとの違いをinvokeと権限の実物で解説」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。