Tauriでハローワールドを画面に出したい

## はじめに

[Electronの代替を目指す軽量なRust製フレームワーク「Tauri」、リリース候補版に到達
2022年3月2日](https://www.publickey1.jp/blog/22/electronrusttauri.html)

rustもJavaScriptもよく知らないけど、試してみる

**最終形は[こちら](#実際に動作している様子)**（GIFアニメーションあり）

### 環境構築

[Setting Up Windows](https://tauri.studio/docs/getting-started/setting-up-windows)にしたがって環境をつくる

- Windows 11 Home
  - Win11であれば、`WebView2`はプリインストールされているらしい
- Visual Studio 2022 Community
  - C++2019再頒布パッケージ
- Node.js
  - 公式では`nvm`や`yarn`を推しているが、入れ替えるのが面倒なので`npm`のまま

#### アップデート後のバージョン情報

##### rust

```bash
rustup update
```

```bash
> rustc --version
rustc 1.60.0
> cargo --version
cargo 1.60.0
> rustup --version
rustup 1.24.3
```

##### npm

```bash
> npm update npm
> npm --version
8.7.0
```

## `tauri`プロジェクト第一歩

Visual Studio Codeのターミナルで作業する

### プロジェクトを作成する

プロジェクト名など尋ねられるが、すべてデフォルトにした（＝エンターキーを連打した）

```bash
npx create-tauri-app
```

成功すると次のコマンドを指示されるが、いったん公式通りに`npm run tauri info`を実行する

```bash
Your installation completed.

$ cd tauri-app
$ npm install
$ npm run tauri dev
```

#### プロジェクトのセットアップを確認する

以降、作成したプロジェクトの階層で作業する

```bash
cd tauri-app
npm run tauri info
```

##### セットアップの出力結果

```bash
Environment
  › OS: Windows 10.0.22000 X64
  › Webview2: 100.0.1185.44
  › MSVC: 
  › Node.js: 16.14.2
  › npm: 8.7.0
  › pnpm: Not installed!
  › yarn: 1.22.4
  › rustup: 1.24.3
  › rustc: 1.60.0
  › cargo: 1.60.0
  › Rust toolchain: stable-x86_64-pc-windows-msvc 

Packages
  › @tauri-apps/cli [NPM]: 1.0.0-rc.7(outdated, latest: 1.0.0-rc.8)
  › @tauri-apps/api [NPM]: 1.0.0-rc.3(outdated, latest: 1.0.0-rc.3)
  › tauri [RUST]: 1.0.0-rc.5 (no lockfile),
  › tauri-build [RUST]: no manifest (no lockfile),
  › tao [RUST]: no manifest (no lockfile),
  › wry [RUST]: no manifest (no lockfile),

App
  › build-type: bundle
  › CSP: unset
  › distDir: ../dist
  › devPath: ../dist

App directory structure
  ├─ dist
  ├─ node_modules
  └─ src-tauri
```

公式だとApp directory structureに`.git`の文字があるが、上記出力結果にはない

そのため手作業でプロジェクトをgit管理下におく作業をする

作業と言っても、`git init`して[.gitignore](https://github.com/tauri-apps/tauri/blob/dev/.gitignore)も追加するだけ
（[こちらの.gitignore](https://github.com/chippers/hello_tauri/blob/main/.gitignore)が最小の構成かと思われる）

ちなみに`cargo new`でつくったプロジェクトの`.gitignore`には`node_modules`が入っていないので流用できなかった

### プロジェクトをビルドして実行する

初回`npm install`には数分かかる

```bash
npm install
npm run tauri dev
```

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/3d79a271-d763-500a-8865-d2a9b92bb0eb.png)


## プロジェクトの中身を変更する

Reactは聞いたことがあったが、バニラJS[^1]と言われてもピンとこなかった

[^1]: [なぜ素の JS のことを Vanilla と呼ぶのか調べてみた](https://zenn.dev/seya/articles/66809b3d59151c)

そんな知識レベルではあるものの、ボタンを押してハローワールドくらいしてみたい

### `main.rs`を書き換える

こちらがいわゆるバックエンドってやつだと思う（ふわっとした知識）

公式の[Creating Rust Commands](https://tauri.studio/docs/guides/command)の章を参考に進める

動きとしては、画面のボタンが押されたときに、画面に表示したいメッセージを返すこととする

`main`にハンドラーを追加して、その実装となる関数も追加した

```rust:main.rs
fn main() {
  tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![my_custom_command]) // この行追加
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

// この関数を追加
#[tauri::command]
fn my_custom_command() -> String {
  "こんにちは、世界！！".into()
}
```

関数の上のアノテーションっぽいやつとか、`.into()`の意味はわからない

### `tauri.conf.json`を書き換える

ボタンをつくるときに、下記のように指示されたので、
APIを呼び出すために、`json`ファイルに1行追加する

> // With the Tauri global script, enabled when `tauri.conf.json > build > withGlobalTauri` is set to true:

```json:tauri.conf.json
  "build": {
    "distDir": "../dist",
    "devPath": "../dist",
    "beforeDevCommand": "",
    "beforeBuildCommand": "",
    "withGlobalTauri": true
  },
```

追加したのは最後の1行だけ

`withiGrobalTauri`の[公式リファレンスはこちら](https://tauri.studio/docs/api/js/modules/tauri)

### `index.html`を書き換える

`<body>`タグの中にJavaScriptを書く（JavaScriptを書く日が来るなんて！）

```js:index.html
  <body>
    <h1>tauri-app</h1>

    // 画面の要素を配置する
    <button id="button">ハローワールドのボタン</button>
    <div id="label"></div>

    // これがJavaScript
    <script>
      const invoke = window.__TAURI__.invoke
      const button = document.querySelector('#button')
      const label = document.querySelector('#label')
      
      // ボタンが押されたときの動作
      button.addEventListener('click', () => {
          invoke('my_custom_command')
          .then(displayMessage)
      })

      function displayMessage(message) {
        label.innerText = message
      }
    </script>
  </body>
```

ボタンを1つ、文字表示用の空の`<div>`を1つ配置した

また、コードには載せていないが、日本語のテストも兼ねて`<meta>`タグに文字コードUTF8を指定した

#### `<script>`タグ内の説明

1. ボタンクリック時に、さきほどつくったrust側のボタンコマンドを呼び出す
2. `invoke`のあとの`.then`により、コマンドの戻り値（メッセージ）を`display~~`関数に渡す
3. `div`タグには`label`idを振っているので、そこにメッセージを表示する

一度きりの動作、クリアコマンドはない

## 実際に動作している様子

ボタンを押したら、その横にメッセージが表示される

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/cab20cc1-6bb6-f25d-bcff-100681c2bef6.gif)

## おわりに

tauriプロジェクト生成時にいろんなフレームワークが選べるみたいなので
次やるなら、Reactとか使ってみたい

## 参考

- [Rust によるデスクトップアプリケーションフレームワーク Tauri](https://developer.mamezou-tech.com/blogs/2022/03/06/tauri/)
- [rustの日本語版ドキュメント](https://doc.rust-jp.rs/book-ja/)