Closed5

Tauri を使ってみる

Kenta WatashimaKenta Watashima

https://tauri.app/

pnpm create tauri-app で雛形生成。

✔ Project name · tauri-example
✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, bun)
✔ Choose your package manager · pnpm
✔ Choose your UI template · React - (https://react.dev/)
✔ Choose your UI flavor · TypeScript

プロジェクトのディレクトリが生成される。

以下のコマンドを叩けば、アプリが立ち上がる。

cd tauri-example
pnpm install
pnpm tauri dev

Kenta WatashimaKenta Watashima

Web (JS) と Rust の連携には Command という仕組みを使う。

https://tauri.app/v1/guides/features/command/

関数のアノテーションに #[tauri::command] を追加して Command を宣言する。

src-tauri/src/main.rs
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

#[tauri::command]
fn my_custom_command() {
    println!("I was invoked from JS!");
}

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![my_custom_command])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

JS (TS) から呼び出す。

import { invoke } from '@tauri-apps/api/tauri'

invoke('my_custom_command')

ちなみに Rust の style guide では、インデントは半角スペース 4 個がマストとされているらしい。

Each level of indentation must be 4 spaces (that is, all indentation outside of string literals and comments must be a multiple of 4).
https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/src#formatting-conventions

Kenta WatashimaKenta Watashima

引数と返り値

src-tauri/src/main.rs
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

#[tauri::command(rename_all = "snake_case")]
fn greet(invoke_message: String) -> String {
    format!("{} World!", invoke_message)
}

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

JS (React) 側から greet を呼び出す。

src/App.tsx
import { useEffect, useState } from "react";
import { invoke } from "@tauri-apps/api/tauri";

function App() {
  const [message, setMessage] = useState('');

  useEffect(() => {
    (async () => {
      const message = await invoke<string>('greet', { invoke_message: 'Hello' })
      setMessage(message);
    })();
  }, [])

  return (
    <div>
      <h1>{message}</h1>
    </div>
  );
}

export default App;

Rust 側へは JSON オブジェクトとして渡す。デフォルトの場合、Rust 側でスネークケースを使って引数を宣言すると、JS 側ではキャメルケースに変換される。つまり invoke('greet', { invokeMessage: 'hello' }) とする必要がある。Command のアノテーションで #[tauri::command(rename_all = "snake_case")] と宣言すればスネークケースのままになる。

Kenta WatashimaKenta Watashima

Python をバックエンドとして組み込む

Python で書いたスクリプトを Tauri アプリのバックエンドとして組み込んでみる。

Python スクリプトは src-python 以下に適当なものを用意。

src-python/test.py
print("Hello from Python")

package.json に下記を追加。

package.json
"scripts": {
  "setup-python": "python -m venv .venv && . ./.venv/bin/activate && pip install -r requirements.txt",
  "build-python": ". ./.venv/bin/activate && pyinstaller -F src-python/test.py --distpath src-tauri/bin --clean -n test-aarch64-apple-darwin"
}

仮想環境を用意し、その環境下で pyinstaller をインストール。pyinstaller で Python スクリプトを実行可能なファイルにビルドする。

tauri.conf.json を編集する。

src-tauri/tauri.conf.json
{
  "tauri": {
    "allowlist": {
      "shell": {
        "sidecar": true,
        "scope": [
          {
            "name": "bin/test",
            "sidecar": true,
            "args": true
          }
        ]
      }
    },
    "bundle": {
      "externalBin": [
        "bin/test"
      ]
    },
  }
}

あとは、フロント側から Command 経由でバイナリを呼び出せばよい。

src/App.tsx
import { useEffect, useState } from "react";
import { Command } from '@tauri-apps/api/shell';

function App() {
  const [message, setMessage] = useState("");

  useEffect(() => {
    (async () => {
      const command = Command.sidecar("bin/test")
      const output = await command.execute();
      setMessage(output.stdout);
    })();
  }, [])

  return (
    <div>
      <h1>{message}</h1>
    </div>
  );
}

export default App;

Kenta WatashimaKenta Watashima

データの永続化

https://github.com/tauri-apps/tauri-plugin-store

設定ファイルのようなものをつくる必要があったのだけど、このプラグインで対応できた。
使い方もシンプル。

import { Store } from "tauri-plugin-store-api";

const store = new Store(".settings.dat");

await store.set("some-key", { value: 5 });

const val = await store.get("some-key");
assert(val, { value: 5 });

await store.save(); // this manually saves the store, otherwise the store is only saved when your app is closed

https://github.com/harshkhandeparkar/tauri-settings

これでもたぶんいけそう。試してはいない。

このスクラップは6ヶ月前にクローズされました