3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Tauri 2.x】における注意点と開発方法

目次

  • はじめに
  • tauriの基本
  • Tauri 2.xの主要な変更点
  • ハマるところ
  • 開発について
  • 注意

はじめに

Tauri 2.x系 (ここではv2.5.1) の開発は非常に快適ですが、プレリリース版ゆえの不安定さや仕様変更により、依存関係のバージョン管理で思いがけないトラブルに遭遇することがあります。

Tauriの基本(Invoke / Emit)

Tauriの連携は、基本的に以下のパターンで行われます。

Node/Frontend → Rust: invoke で Rustの関数(コマンド)を呼び出す。

Rust → Node/Frontend: emit でイベントを発行し、Node側で on で受け取る。

tsc, typescript, reactを入れる想定
node側からの呼び出し

import { invoke } from "./@tauri-apps/api/core"; //ここがapiからcoreになりました

function inoke_rust(){
    invoke ("server", arg);
}

return {
    <buttion onclick="invoke_rust"></button>

}

rust側はuseしなくても基本的なtauriは動作する

use tauri::command;

#[tauri::command]
fn server(arg){
    //server cluc
    let arg = test;
}

本記事では、私が直面した以下の2つの主要な問題の切り分けと解決策、そして動作確認済みの設定ファイルを共有します。

  • npmとRustクレート間でのマイナーバージョン不一致ビルドエラー

  • Invokeコマンドの引数における命名規則の問題

前提とする環境構成

  • OS: Linux (Windows/macOSでもRust環境があれば共通の解決策が適用可能です)

  • Frontend: React + TypeScript (Vite)

  • Backend: Rust (Tauri 2.x)私はとりあえず2.5.1で提示させていただきます。

Tauri 2.xの主要な変更点(InvokeとAPI)

変更点1: APIのパス変更

@tauri-apps/api のコア機能(invoke や on など)は、@tauri-apps/api/core へと移動しました。

変更前 (1.x): import { invoke } from "@tauri-apps/api";

変更後 (2.x): import { invoke } from "@tauri-apps/api/core";
Tauri 1.xから2.xへの移行で、最も重要な変更の一つが @tauri-apps/api の構造変更です。

変更点2: Rustコマンドの基本構造

Rust側は引き続き #[tauri::command] マクロを使用します。

use tauri::{Builder};

#[tauri::command]
fn app1(arg: String) {
    // server logic here
    println!("Received arg: {}", arg);
}

最大のハマりどころ:Invoke引数の命名規則

Tauri 2.xで特に注意が必要なのが、JavaScript側とRust側の引数名のマッピングです。

結論: Rust側の引数名もキャメルケース (camelCase) に合わせる必要があります。

Tauriは、JavaScript側の標準的な命名規則であるキャメルケースの引数名が、Rust側のスネークケース (snake_case) の引数名と**自動で一致すると期待しますが、これが意図通りに動作しないことがあります。**特に引数が一つではない場合や構造が複雑な場合、厳密な一致が求められます。

エラーになる例 (Rust側がスネークケースの場合)

JavaScript (キャメルケース)

// ipA (キャメル) を渡そうとしている
invoke("rust_fun", {
    ipA: "192.168.1.1", 
    port: 8080
});

Rust (スネークケース)


#[tauri::command]
fn rust_fun(
    ip_a: String, // スネークケース
    port: u16,
) {
    // ...
}

→ この組み合わせはエラーになる可能性が高い

解決策 (Rust側もキャメルケースに合わせる)

Rustの標準的な慣習はスネークケースですが、TauriのInvokeハンドラに関しては、JSの慣習であるキャメルケースに合わせることで確実になります。

Rust (キャメルケース)

#[tauri::command]
fn rust_fun(
    ipA: String, // 解決策:キャメルケースに統一
    port: u16,
) {
    // ...
}

発生したエラー (バージョン不一致)

久しぶりにcargo tauri build 時に以下のエラーが発生しました。

Error Found version mismatched Tauri packages. Make sure the NPM package and Rust crate versions are on the same major/minor releases:
tauri (v2.5.1) : @tauri-apps/api (v2.6.0)

または、NPM側が追いついていないバージョンを参照するエラーです。
npm ERR! notarget No matching version found for @tauri-apps/api@2.5.1.

まぁAPI形が変わっていないから上げる必要がないのでしょうが、、、

開発について

一番楽な開発スタート

'npm install tauri-latest'

node周りは普通の開発と同じですのでrustのmainコードを示します
rust

use tauri::{Builder};

#[tokio::main]
async fn main() {

    println!("App start");

    Builder::default()
        // generate_handler!に複数のコマンドを渡せます
        .invoke_handler(tauri::generate_handler![
            app1,
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

npmのパッケージ

npmのパッケージもrustとversionが1:1出ないことに注意

package.json

{
  "name": "tauri-app",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "tauri": "tauri"
  },
  "dependencies": {
    "@tauri-apps/api": "2.5.0",
    "@tauri-apps/plugin-opener": "^2",
    "chart.js": "^4.5.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^7.6.2"
  },
  "devDependencies": {
    "@tauri-apps/cli": "2.5.0",
    "@types/react": "^18.3.1",
    "@types/react-dom": "^18.3.1",
    "@vitejs/plugin-react": "^4.3.4",
    "autoprefixer": "^10.4.21",
    "postcss": "^8.5.6",
    "tailwindcss": "^4.1.10",
    "typescript": "~5.6.2",
    "vite": "^6.0.3"
  }
}

キャロットはやめておくことを推奨
ここでrustはtauri2.5.1だが、
nodeは2.5.0までしか出ていない
昔はキャロットでも行けたり、できる場合もあるが、、、

一応tsのjson

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

vite

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

// @ts-expect-error process is a nodejs global
const host = process.env.TAURI_DEV_HOST;

// https://vitejs.dev/config/
export default defineConfig(async () => ({
  plugins: [react()],
  root: './src',

  // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
  //
  // 1. prevent vite from obscuring rust errors
  clearScreen: false,
  // 2. tauri expects a fixed port, fail if that port is not available
  server: {
    port: 1420,
    strictPort: true,
    host: host || false,
    hmr: host
      ? {
          protocol: "ws",
          host,
          port: 1421,
        }
      : undefined,
    watch: {
      // 3. tell vite to ignore watching `src-tauri`
      ignored: ["**/src-tauri/**"],
    },
  },
  build: {
 	outDir: '../../dist' 
  }
}));

注意

現在tauri 2.5.1は脆弱性が確認されているようです!
localの動作に留めるなど、してください
私もtauriの依存をを追いますが、とりあえず2.x系への以降が大変かと思いますが、2.xまで行ってしまえば大きなAPI修正はないと思います。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?