🦀

[Rust]はじめてのデスクトップアプリ開発 with React × Tauri

2022/07/14に公開

はじめに

Rust初心者です
Rustについて調べていた際に「Rustでデスクトップアプリが作れる」という記事を見かけ、
気になって触ってみました!
Rustで生成したprint文をReactで表示する簡単なデスクトップアプリケーションを作成してみます

概要

  • MacOSでのReact × Tauriで簡単なデスクトップアプリの作成
    ※Rustのインストールについてはこちらをご参照ください

Tauriとは

TauriはRustで作られたデスクトップアプリケーションのツールキットになります

  • HTML/CSSとJS(とそのフレームワークも含む)で作成できる
  • バンドルサイズが小さい
  • クロスプラットフォームアプリを作成できる
    といった特徴があります
    公式

Tauri CLIのインストール

まずはじめにTauri CLIをインストールします
cargoからインストールする方法と、npmなどのパッケージマネージャー経由でインストールする方法があります
公式では

We also compile the CLI as a native Node.js addon and distribute it via NPM. This has a number of advantages compared to the Cargo installation method:
1.The CLI is pre-compiled, leading to much faster install times
2.You can pin a specific version in your package.json file
3.If you develop custom tooling around Tauri, you can import the CLI as a regular JavaScript module

とあるため、今回はnpm経由でインストールします

  • npm経由でインストールする場合
npm install --save-dev @tauri-apps/cli

※5秒くらいで終わりました

package.json も下記の通り編集します

package.json
{
  // This content is just a sample
  "scripts": {
    "tauri": "tauri"
  }
}

cargoでインストールする場合はこちらになります

  • cargo経由でインストールする場合
cargo install tauri-cli --version "^1.0.0"

※こちらは10~15分程度かかりました

Tauriプロジェクトの作成

npm create tauri-app でTauriプロジェクトを作成します
今回はJSのフレームワークとしてReact(Typescript)を選択しました

npm create tauri-app
Need to install the following packages:
  create-tauri-app
Ok to proceed? (y) y

We hope to help you create something special with Tauri!
You will have a choice of one of the UI frameworks supported by the greater web tech community.
This tool should get you quickly started. See our docs at https://tauri.app/

If you haven't already, please take a moment to setup your system.
You may find the requirements here: https://tauri.app/v1/guides/getting-started/prerequisites
    
Press any key to continue...
? What is your app name? tauri-app
? What should the window title be? Tauri App
? What UI recipe would you like to add? create-react-app //★create-react-appを選択
(https://create-react-app.dev/)
? Add "@tauri-apps/api" npm package? Yes
? Which create-react-app template would you like to use? 
create-react-app (Typescript) //★Typescriptを選択
>> Running initial command(s)
Need to install the following packages:
  create-react-app@latest
Ok to proceed? (y) y

※インストールに3分ほどかかります

続いて npm run tauri dev してアプリケーションを起動します

npm run tauri dev

はじめてのデスクトップアプリが起動しました!
見慣れたウィンドウの中に自分の作ったアプリがあると思うと感動しますね!(まだなにもしてないですが、、笑)

ホットリロードも効いてました!

ソースコードの編集

Rust側の編集

ReactからRustのコードを呼び出せるように編集していきます
まず、tauri-app 配下の src-tauri/src/main.rs に関数を追加します
追加した関数の頭に #[tauri::command] コマンドをつけることで、React側から呼び出し可能な関数になります

src-tauri/src/main.rs
#[tauri::command]
fn greet(name: &str) -> String {
    format!("{} {}", name, "さんこんにちわ!")
}

次に、作成したコマンドをmain関数の中でTauriに通知します

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

React側の編集

React側では、"@tauri-apps/api" から invoke をインポートし、
非同期で呼び出しを行います

下記の通り src/App.tsx を修正します

src/App.tsx
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import { useState, useRef } from "react"; // 追加
import { invoke } from "@tauri-apps/api"; // 追加

function App() {
  const [message, setMessage] = useState("");
  const inputRef = useRef<HTMLInputElement>(null!);

  const messageHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMessage(e.target.value);
    console.log(message);
  };

  const GreetHandler = async (
    name: string,
    inputRef: React.MutableRefObject<HTMLInputElement> | null
  ) => {
    const response: string = await invoke("greet", { name: name });
    alert(response);
    setMessage("");

    if (inputRef === null) {
      return;
    }
    inputRef.current.value = "";
  };

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React & Tauri !!
        </a>
        {/* 追加 */}
        <p>メッセージ: {message}</p>
        <input ref={inputRef} type="text" onChange={(e) => messageHandler(e)} />
        <button onClick={() => GreetHandler(message, inputRef)}>
          ようこそ
        </button>
      </header>
    </div>
  );
}

export default App;

編集結果を確認してみます

Macでは、ディバロッパーツールは Cmd + Option + i で開くことができます

参考: Open WebView Dev Tools on startup

おわりに

ReactとTauriではじめてのデスクトップアプリケーションを作成しました!
Tauriを触りつつ、Rustの理解も深めていきたいと思います!

参考

Tauri公式ドキュメント
Tauriで使えるWebフレームワークたち(VSCodeのプラグインも添えて)
[サンプルコード]TauriでReact×Rustなデスクトップアプリを作った
tauri (react) 試す
@tauri-apps/api
Open WebView Dev Tools on startup

Discussion