Tauri 触ってみる
Quick Start を進めていく
Prerequisites
macOS 用の setup を進める
Vite quickstart
frontend は Vite + React + TS で進めていく
Scaffolding
project を scaffolding
npm create tauri-app
✔ Project name · tauri-quick-start-vite
✔ Choose your package manager · npm
✔ Choose your UI template · react-ts
Please follow https://tauri.app/v1/guides/getting-started/prerequisites to install the needed prerequisites, if you haven't already.
Done, Now run:
cd tauri-quick-start-vite
npm install
npm run tauri dev
生成されるものは、こんな感じ↓
├── README.md
├── index.html
├── package.json
├── public
│ ├── tauri.svg
│ └── vite.svg
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ └── react.svg
│ ├── main.tsx
│ ├── style.css
│ └── vite-env.d.ts
├── src-tauri
│ ├── Cargo.toml
│ ├── build.rs
│ ├── icons
│ │ ├── 128x128.png
│ │ ├── 128x128@2x.png
│ │ ├── 32x32.png
│ │ ├── Square107x107Logo.png
│ │ ├── Square142x142Logo.png
│ │ ├── Square150x150Logo.png
│ │ ├── Square284x284Logo.png
│ │ ├── Square30x30Logo.png
│ │ ├── Square310x310Logo.png
│ │ ├── Square44x44Logo.png
│ │ ├── Square71x71Logo.png
│ │ ├── Square89x89Logo.png
│ │ ├── StoreLogo.png
│ │ ├── icon.icns
│ │ ├── icon.ico
│ │ └── icon.png
│ ├── src
│ │ └── main.rs
│ └── tauri.conf.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
見た感じ、
src: お馴染みの frontend のコード
src-tauri: Rust のコード
が生成されてる
npm create tauri-app は以下のチャプターで行う手順を一発でやってくれてたみたい
仮に既存の project を tauri に載っけたい場合は、"Create the Rust Project" の手順に従えばよさそう
実行
cd tauri-quick-start-vite
npm install
npm run tauri dev

Invoke Commands
Tauri lets you enhance your frontend with native capabilities. We call these Commands, essentially Rust functions that you can call from your frontend JavaScript. This enables you to handle heavy processing or calls to the OS in much more performant Rust code.
Commands: OS native の機能を frontend 側で利用できるように Tauri が提供する api
例: greet Command を Rust で定義し、frontend 側で呼び出す
(Rust) greet Command 作成
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
(frontend) '@tauri-apps/api を通して、greet commad を invoke
import { invoke } from '@tauri-apps/api'
// now we can call our Command!
// Right-click the application background and open the developer tools.
// You will see "Hello, World!" printed in the console!
invoke('greet', { name: 'World' })
// `invoke` returns a Promise
.then((response) => console.log(response))
Using withGlobalTauri
@tauri-apps/api を利用せずに、window に api を生やすこともできるらしい
{
"build": {
"beforeBuildCommand": "npm run build",
"beforeDevCommand": "npm run dev",
"devPath": "http://localhost:3000",
"distDir": "../build",
+ "withGlobalTauri": true
},
@tauri-apps/api
@tauri-apps/api package に、js/ts で利用できる Native 機能用の api が存在するので試してみる。
fs
Access the file system.
fs を利用して file system にアクセスしてみる
tauri.conf.json 更新
tauri.conf.json で fs を許可してあげる
{
"tauri": {
"allowlist": {
"fs": {
"all": true, // enable all FS APIs
"readFile": true,
"writeFile": true,
"readDir": true,
"copyFile": true,
"createDir": true,
"removeDir": true,
"removeFile": true,
"renameFile": true,
"exists": true
}
}
}
}
Security
This module prevents path traversal, not allowing absolute paths or parent dir components (i.e. "/usr/path/to/file" or "../path/to/file" paths are not allowed). Paths accessed with this API must be relative to one of the base directories so if you need access to arbitrary filesystem paths, you must write such logic on the core layer instead.
- absolute path
- parent dir
にはアクセスできないらしい
基本的に、以下の base directories 下ならOK。
それ以外の場合は、別途 core layer (なにこれ?Rust 側のコードか?) でロジックを書けばいけるらしい。
The scope configuration is an array of glob patterns describing folder paths that are allowed. For instance, this scope configuration only allows accessing files on the databases folder of the $APP directory:
アクセス可能な scope を tauri.allowlist.fs.scope で設定。デフォでは [] なので、設定しないとアクセスできないぽい。
{
"tauri": {
"allowlist": {
"fs": {
"scope": ["$APP/databases/*"]
}
}
}
}
Notice the use of the $APP variable. The value is injected at runtime, resolving to the app directory. The available variables are: $AUDIO, $CACHE, $CONFIG, $DATA, $LOCALDATA, $DESKTOP, $DOCUMENT, $DOWNLOAD, $EXE, $FONT, $HOME, $PICTURE, $PUBLIC, $RUNTIME, $TEMPLATE, $VIDEO, $RESOURCE, $APP, $LOG, $TEMP.
scope 指定時に $APP のように runtime で値が決まる変数を使用できる。
以下が使用可能な変数↓
$AUDIO, $CACHE, $CONFIG, $DATA, $LOCALDATA, $DESKTOP, $DOCUMENT, $DOWNLOAD, $EXE, $FONT, $HOME, $PICTURE, $PUBLIC, $RUNTIME, $TEMPLATE, $VIDEO, $RESOURCE, $APP, $LOG, $TEMP
File 書き込みしてみる
-
tauri.conf.jsonで download directory への書き込みを許可
"tauri": {
"allowlist": {
"fs": {
"all": true, // 書き込みを含む全ての操作を許可
"scope": ["$DOWNLOAD/*"] // download directory への書き込みを許可
},
"dialog": {
"message": true // alert できるように
}
},
//...
-
@tauri-apps/api/fsのwriteTextFileでファイル書き込み
import { BaseDirectory, writeTextFile } from '@tauri-apps/api/fs';
import { useState } from 'react';
import './CreateFile.css';
export const CreateFile = () => {
const [fileName, setFileName] = useState('');
const [content, setContent] = useState('');
return (
<div className='create-file'>
<input value={fileName} onChange={(e) => setFileName(e.target.value)} />
<textarea
rows={10}
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<button
onClick={async () => {
if (!fileName) {
alert('Enter FileName');
return;
}
if (!content) {
alert('Enter content');
return;
}
try {
await writeTextFile(fileName, content, {
dir: BaseDirectory.Download,
});
alert('Success');
} catch (e) {
alert(e);
}
}}
>
Create New File
</button>
</div>
);
};


download directory に "sample.txt" が作成された、OK
alert 使おうとしたらエラー出た
Unhandled Promise Rejection: 'dialog > message' not in the allowlist (https://tauri.app/docs/api/config#tauri.allowlist)
CreateFile.tsx:31
dialog > message を allowlist に加えないといけないみたい
これでいける
{
"tauri": {
"allowlist": {
"dialog": {
"message": true,
}
}
}
}