モチベーション
tauriはwebview2(OS内蔵)でGUIアプリケーションを作らせてくれる。似たようなフレームワークにelectronがあるがこれはchromiumを同梱するため容量・メモリ使用量が大きくまたセキュリティアップデートが(一応)必要なため、少し避けていた。もちろん意図せずアップデートされないのでレイアウトが崩れるなどの心配は不要だがそこまで気にするアプリを作るわけではないためメリットに対してのデメリットの強さがどうしてもあった。
その点tauriは便利そう、ということでtauriのAPIがこなれるまで待っていた。v2になったことで雰囲気破壊的変更はしつくしたのではないか、ということで着手してみた。
その結果それなりに苦労したので初期セットアップに必要そうな点をまとめた。
使ってみた所感
- 良い点
- 導入が楽。公式リファレンスにデバッグ・ビルドまで記載してある。すばらしい
- 今回の構成だと15MBほど、electronと比べると小さい(と思う。最近ビルドしていないので正確なサイズは知らない)
- フロント・バック共にホットリロード完備。starterに含まれているのは本当に楽
- 困る点
- 地味にビルド時間が長い。ほぼ実装していない状態であっても、依存ライブラリが多いのか10秒以上は待つ。大規模アプリを作成した場合にどうなるのかがやや不安だが、そんなものは作る予定が無いのでどうでもよい
- (Rustの実装が難しい)
バージョン
主要なものだけ。どれが主要かはよくわかっていない。
| ライブラリ | バージョン |
|---|---|
| cargo | 1.82.0 |
| rustc | 1.82.0 |
| tauri | 2.1.1 |
| tauri-build | 2.0.3 |
| @tauri-apps/api | 2.2.0 |
プロジェクト作成
https://v2.tauri.app/start/ を参考にセットアップ。特に苦労はない。以下やや古いログ
1>bun create tauri-app
2✔ Project name · tauri-app
3✔ Identifier · com.tauri-app.app
4✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, deno, bun)
5✔ Choose your package manager · bun
6? Choose your UI template ›
7❯ Vanilla
8 Vue
9 Svelte
10 React
11 Solid
12 Angular
13 Preact
14✔ Choose your UI flavor · TypeScript
15
16Template created!
17
18Your system is missing dependencies (or they do not exist in $PATH):
19╭─────┬───────────────────────╮
20│ Bun │ Visit https://bun.sh/ │
21╰─────┴───────────────────────╯
22
23Make sure you have installed the prerequisites for your OS: https://tauri.app/start/prerequisites/, then run:
24 cd tauri-app
25 bun install
26 bun run tauri android init
27
28For Desktop development, run:
29 bun run tauri dev
30
31For Android development, run:
32 bun run tauri android dev
33
34>cd tauri-app
35>bun install
36bun install v1.1.34 (5e5e7c60)
37
38+ @sveltejs/adapter-static@3.0.8
39+ @sveltejs/kit@2.15.1
40+ @sveltejs/vite-plugin-svelte@5.0.3
41+ @tauri-apps/cli@2.1.0
42+ svelte@5.16.0
43+ svelte-check@4.1.1
44+ typescript@5.6.3 (v5.7.2 available)
45+ vite@6.0.6
46+ @tauri-apps/api@2.1.1
47+ @tauri-apps/plugin-opener@2.2.2
48
49tauri-app>bun run tauri android init
50$ tauri android init
51action request: to initialize Android environment; Android support won't be usable until you fix the issue below and
52re-run `tauri android init`!
53 Have you installed the Android SDK? The `ANDROID_HOME` environment variable isn't set, and is required: environment
54 variable not found
55victory: Project generated successfully!
56 Make cool apps! 🌻 🐕 🎉
判断したポイント
- package manager
- bunにしてみた
- 何でもよいが最終的にフロントエンド開発もあるためこちらも合わせた環境で管理したい。そのためcargoではなくnode.js系列で適当なものとした。
- しかしtypescriptを選択したのは失敗だった。viteでのビルドが挟まるためやや難易度増加。またtypescriptが必要なほど大規模な開発をしない。
- UI template
- tauriの構造を学ぶのが目的のためVanilla
bun run tauri android init- androidの開発環境は不要なので飛ばす
最終配置
1/
2|- dist
3 |- jquery.min.js ★2
4|- public ★1
5 |- lib
6 |- jquery.min.js
7 |- main.ts
8|- src-tauri
9 |- tauri.conf.json
10 |- target
11 |- release
12 |- resource
13 |- tauri-app.exe ★3
14|- tsconfig.json
★はビルド時にコピーされる。★1→★2はviteのビルド、★2→★3はtauriのビルド。
今回はローカルに配置したjqueryを例に進める。また以降大体の区分けで説明を記載するが、区分けた内容以外の設定も混ぜている。説明は手を抜いているが多分わかる範囲だと思う(着手から完了まで時間がかかり、そしてメモしていない点が少しあるため)。
CSPの設定
まずtauriがローカルファイルにアクセスできるようにする。CSPについてはアプリ開発者のにとっての Tauri v2 のセキュリティ構造を読み解くが丁寧に解説してくださっているのでこちらを参照。外部へのアクセスは想定しないためセキュリティについてはそこまでがんばらない、緩くするだけ。
これらの設定によりimport { convertFileSrc } from '@tauri-apps/api/core';からなるconvertFileSrcで変換すれば、フロントエンドは「http://asset.localhost/ファイル名」のような形にしてtauri(バックエンド)からダウンロードできるようになる。あとはfetchなどでいい感じにダウンロードすればよい。
1- "identifier": "com.tauri-app.app",
2+ "identifier": "com.tauri-app-test.app",
3 "app": {
4 "withGlobalTauri": true,
5 "windows": [
6 {
7 "title": "tauri-app",
8 "width": 800,
9 "height": 600
10 }
11 ],
12 "security": {
13+ "csp": {
14+ "default-src" : "'self' ",
15+ "connect-src": "ipc: http://ipc.localhost https://ipc.localhost",
16+ "img-src": "'self' asset: http://asset.localhost https://asset.localhost blob: data:",
17+ "font-src": "'self' asset: http://asset.localhost https://asset.localhost blob: data:",
18+ "script-src": "'self' asset: http://asset.localhost https://asset.localhost",
19+ "style-src": "'unsafe-inline' 'self'"
20+ },
21+ "assetProtocol": {
22+ "enable": true,
23+ "scope": ["**"]
24+ }
25 }
26 },
27 "bundle": {
28 "active": true,
29 "targets": "all",
30 "icon": [
31 "icons/32x32.png",
32 "icons/128x128.png",
33 "icons/128x128@2x.png",
34 "icons/icon.icns",
35 "icons/icon.ico"
36 ],
37+ "resources": [
38+ "resources/**/*"
39+ ]
40 }
- cspの設定
- csp以外にもついでにリソースディレクトリの追加なども実施
identifierを任意の値に変更resourcesを追加。ここにtauriから参照したいファイルを置く想定
ローカルファイルを含めてビルドする
CSPを設定することでtauriはローカルファイルにアクセスできるようになった。しかし、exeを作成し起動してみると、ビルド時点で含まれていることを期待するファイルが上手く読み取れないことがわかった。これはexe作成時に同梱したいファイルが存在せずそもそも同梱されていないことが原因だった。そのため同梱するために次のように構成を変更した。
/src-tauri/tauri.conf.json
1 "build": {
2 "frontendDist": "../dist"
3 }
※変更なし。説明のため記述
/tsconfig.json
1- "include": ["src"]
2+ "include": ["public"]
デフォルトだとsrcを参照している。よくわからないがtauri-appではviteがデフォルトで採用されており、viteはvite.config.tsで指定しない限りソースディレクトリをpublicとして見ている、らしい。そのためpublic以下のファイルをdistに移動させバンドルしようとするが、publicフォルダが無いので何もバンドルされていなかった、のだと思う。viteの設定を変えるよりもtauriの参照先を変える方が楽そうなので、exeにバンドルしたいファイル群はpublicに移すように変更した。
ただ初期設定で違う位置なのでなにか理解できていない理由があるのかもやしらん。
/index.html
1+ <script src="/lib/jquery-3.7.1.min.js"></script>
2- <script type="module" src="/src/main.ts" defer></script>
3+ <script type="module" src="/public/main.ts" defer></script>
/public/lib/jquery-3.7.1.min.jsでもデバッグ時は参照できてしまう。しかしexeにする場合publicは無くなるため、/lib/jquery-3.7.1.min.jsにする必要あり。tsconfig.jsonで設定した位置はルート参照できるようにしてくれている、らしい。
なおこれはviteでビルドされるものにはビルドするためなのか適用してはいけない。typescriptやcssはpublicありのパス指定が必要であり、javascriptなどはpublicなしのパス指定が必要。そのためts系列はsrcフォルダに入れたままでも問題はない。
開発者ツールの有効化
(順序が逆だが)デバッグ時に上手くいっているものの、exe作成後にうまくいかない場合のデバッグに必要だった。今回はCSPの設定の正しさや、javascriptがロードできない問題の切り分けに用いていた。今後も何か使いそうなのでF12で起動できるようにしてみた。
デバッグ起動であればこの設定をせずともF12を押すことで開発者ツールは表示される。
src-tauri/Cargo.toml
1tauri = { version = "2", features = [
2+ "protocol-asset",
3+ "devtools"
4] }
devtoolsを追加した。
src-tauri/src/main.rs
1+ use once_cell::sync::OnceCell;
2+ static MAIN_WINDOW: OnceCell<tauri::WebviewWindow> = OnceCell::new();
3+
4+ // Tauriコマンド: デバッグツールを開く
5+ #[tauri::command]
6+ fn open_devtool() {
7+ let main_window = MAIN_WINDOW.get().unwrap();
8+ main_window.open_devtools();
9+ }
10
11#[cfg_attr(mobile, tauri::mobile_entry_point)]
12pub fn run() {
13 tauri::Builder::default()
14 .plugin(tauri_plugin_opener::init())
15+ .setup(|app| {
16+ let window = app.get_webview_window("main").unwrap();
17+ #[cfg(debug_assertions)]
18+ {
19+ window.open_devtools();
20+ }
21+ MAIN_WINDOW
22+ .set(window)
23+ .expect("メインウィンドウの設定に失敗しました");
24+ Ok(())
25+ })
26 .invoke_handler(tauri::generate_handler![
27 greet,
28+ open_devtool
29 ])
30 .run(tauri::generate_context!())
31 .expect("error while running tauri application");
32}
デバッグ起動時はどうせ出すので自動で開発者ツールを有効化しておく。リリース時はイベント通知により開発者ツールを有効化するようにする、ここは開発するexeによっては無効化しておいた方が良い。今回のツールは自分で使う用なのでひとまず出せるようにしておく。
src/public/main.ts
1document.body.addEventListener('keydown',
2 async(event) => {
3 if (event.key === 'F12') {
4 await invoke("open_devtool");
5 }
6 }
7);
フロントエンド側でF12を検出したら、バックエンドにメッセージを投げる。それにより開発者ツールが開かれる。
ビルド
ルートフォルダにて
1npm run tauri build
をすると、自動で
1tsc && vite build
を実行しdistにviteのコンパイル結果を置く。その後tauriのビルドをし、src-tauri/target/release以下に成果物を置いてくれる。
インストーラなども用意してくれるが、恐らく必要なのはexeと(使うなら)resourceディレクトリだけなのでこれらを任意の場所に移動させて動作が確認できればOK。インストールしても良いが、実装者のPCでインストールしたところで問題が見つかる気がしないので、いざ誰かに渡すようなことがあった場合に手間取りそう。そのためあまり個人では使う気になれない