Nuxt3+Tauriでデスクトップアプリを作る
はじめに
Electronでデスクトップアプリを作ろうとしたが、vue-routerによるルーターが機能しないうえに起動に時間がかかるためTauriへの移行した際に詰まったところ、やり方等を載せている。
また、Tauriのプラグインを用いてウィンドウ配置を固定するようにもした。
Tauriとは
TauriはRustベースのデスクトップアプリを作成できるオープンソースのフレームワーク。
軽量でElectronと比べインストーラのサイズ、使用メモリが少ないという開発者にとってはありがたい利点がある。また、Rust言語がベースになっているのでセキュリティ的にも堅牢なアプリを作ることができる。
Electronとの違いを軽くまとめてみた。なお、バンドルサイズなどはTauri公式が出しているものを引用している。
比較内容 | Electron | Tauri |
---|---|---|
言語 | JavaScript(Node.js) | Rust |
レンダリング方法 | Chromium | WebView2 |
バンドルサイズ | 52.1MB | 3.1MB |
メモリ使用量 | 462MB | 180MB |
起動時間 | 0.8秒 | 0.39秒 |
Tauriを導入
タイトルにもあるように今回はTauriにNuxt3を導入してアプリケーションを作成していく。Tauriは現在v1とベータ版のv2があり、v2ではNuxt3に関するドキュメントがあるがv1には公式のものはないので追って説明する。
まずは、肝心のTauriのセットアップをしていく。セットアップはTauri ガイドに基づきながら進める。
VS C++ Build Toolのセットアップ
Tauriの動作に必要なRustをインストールしていくのだが、Visual Studio C++ ビルドツールが必須になる。そこで、Visual Studio 2022をダウンロードしてインストールする。
インストーラをダウンロードして実行すると、画像のようなものが表示されるはずだ。
「C++によるデスクトップ開発」にチェックを入れ、右のオプションに「MSVC ... - VS2022 C++ x64/86ビルドツール」と今使用しているWindowsのSDKにチェックが入っていればOK。(Windows 11ならWindows 11 SDKにチェックが入っている必要がある。Windows 10ならWindows 10 SDKの最新版が無難。)
インストール方法はダウンロードしながらでも一括ダウンロードしてからでもどちらでもよい。これでBuild Toolのセットアップは完了。
WebView2のセットアップ
次にTauriの動作に必要なWebView2をセットアップしていくが、Windows 10 1803以降であればアップデート時にインストールされているのでここは必要ない。
もし、1803より前の環境でセットアップを行っている場合はMicrosoftからwebview2をダウンロードできる。
Rustのセットアップ
次にRustup
というRustのインストーラをダウンロードしてインストールしていく。
winget
が使える場合はwinget
経由でもインストールすることができる。
winget install --id Rustlang.Rustup
プロジェクトを作成する
次に、Tauri + Nuxt3のプロジェクトを作っていく。既にNode.jsは導入されているものとして進めていくが導入できていない場合はNode.jsのページからLTS版をダウンロードしてインストールするとよい。(バージョンはv18以上をおすすめする)
Tauri側のセットアップ
まずはTauriのプロジェクトを作っていく。
npm create tauri@latest
✔ Project name · tauri-app
✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, bun)
✔ Choose your package manager · npm
✔ Choose your UI template · Vanilla
✔ Choose your UI flavor · TypeScript
Template created! To get started run:
cd tauri-app
npm install
npm run tauri dev
-
Project name
プロジェクト名。同時にフォルダ名になる。 -
Frontend Language
今回はNuxt.jsを用いるので「Typescript/Javascript」を選択。 -
package manager
お好みで。ここでは一般的なnpm
を用いる。 -
UI template
Tauri v1ではNuxt用のテンプレートがないので、Vanillaを用いる。 -
UI flavor
よく使う方を選ぶ。ここではTypescriptで進める。
プロジェクトが作成されたら、次のようなフォルダ構造になっているはず。
.
├── node_modules/
├── src/
│ ├── assets
│ │ ├── tauri.svg
│ │ ├── typescript.svg
│ │ └── vite.svg
│ ├── main.ts
│ └── styles.css
├── src-tauri/
│ ├── icons/
│ ├── src/
│ │ └── main.rs
│ ├── Cargo.toml
│ ├── build.rs
│ └── tauri.conf.json
├── README.md
├── index.html
├── package.json
├── tsconfig.json
└── vite.config.ts
Nuxt3のセットアップ
次にTauriプロジェクトにNuxt3を導入する。ここでは先ほど作成したプロジェクトtauri-app
を現在のディレクトリ(ルートディレクトリ)として進める。
まずはsrc
フォルダ、node_modules
フォルダ、tsconfig.json
、index.html
、vite.config.ts
は統合するのに不要なファイルとなるので削除する。
この段階でのフォルダ構造はこちら
.
├── src-tauri/
│ ├── icons/
│ ├── src/
│ │ └── main.rs
│ ├── Cargo.toml
│ ├── build.rs
│ └── tauri.conf.json
├── README.md
└── package.json
次に、Nuxt3のプロジェクトを作成する。
npx nuxi@latest init src
フォルダ名はsrc
にする。プロジェクトを作成したらsrcフォルダに移動して、ファイルの整理を行う。まず、nuxt.config.ts
、tsconfig.json
はルートディレクトリに移動させる。
次に、ルートディレクトリのpackage.json
を次のように書き加える。具体的に書き加える、削除するところはハイライトで表示している。
{
"name": "tauri-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"tauri": "tauri",
- "dev": "vite",
- "build": "tsc && vite build",
- "preview": "vite preview",
+ "tauri:dev": "tauri dev",
+ "build": "nuxt build",
+ "dev": "nuxt dev",
+ "generate": "nuxt generate",
+ "preview": "nuxt preview",
+ "postinstall": "nuxt prepare"
},
"dependencies": {
"@tauri-apps/api": "^1",
+ "nuxt": "^3.11.2",
+ "vue": "^3.4.21",
+ "vue-router": "^4.3.0"
},
"devDependencies": {
"@tauri-apps/cli": "^1",
"typescript": "^5.0.2"
}
}
次に.gitignore
も同様に書き換える。ルートディレクトリの.gitignore
を開き、次のように書き換える。
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
.nuxt
.nitro
.cache
.output
.env
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
書き換えが終わったら、srcフォルダ内の次のファイル・フォルダを削除する。
- package.json
- package-lock.json(yarn.lock)
- node_modules/
- public/
- .gitignore
(/がついているのはフォルダ)
これで、Nuxt3のプロジェクトのセットアップが完了した。
最終的なフォルダ構造
.
├── src/
│ ├── assets/
│ │ └── css/
│ │ └── tailwind.css
│ ├── components/
│ ├── pages/
│ │ └── index.vue
│ ├── plugins/
│ ├── public/
│ ├── server/
│ └── app.vue
├── src-tauri/
│ ├── capabilities/
│ │ └── main.json
│ ├── icons/
│ │ ├── icon-512.png
│ │ └── icon.ico
│ ├── src/
│ │ └── main.rs
│ ├── target/
│ ├── .gitignore
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── build.rs
│ └── tauri.conf.json
├── .gitignore
├── README.md
├── nuxt.config.ts
├── package-lock.json
├── package.json
├── tailwind.config.ts
└── tsconfig.json
Tauriの設定変更
このままでは、Tauriが正しくNuxt3プロジェクトを読み込んでくれないので設定を変える。
src-tauriフォルダに移動し、tauri.config.json
を開く。
{
"build": {
"beforeDevCommand": "npm run dev",
- "beforeBuildCommand": "npm run build",
+ "beforeBuildCommand": "npm run generate",
- "devPath": "http://localhost:1420",
+ "devPath": "http://localhost:3000",
"distDir": "../dist",
"withGlobalTauri": true
},
"package": {
"productName": "tauri-app",
"version": "0.0.0"
},
"tauri": {
"allowlist": {
"all": false,
"shell": {
"all": false,
"open": true
}
},
"windows": [
{
"title": "tauri-app",
"width": 800,
"height": 600
}
],
"security": {
"csp": null
},
"bundle": {
"active": true,
"targets": "all",
// identifierを初期から変更しないとビルドに失敗する
- "identifier": "dev.tauri",
+ "identifier: "your-domain",
// ウィンドウのアイコンを変更する場合はiconsフォルダにpng、icoファイルを入れてここで設定
"icon": ["icons/icon-512.png", "icons/icon.ico"]
}
}
}
次に、ルートディレクトリのnuxt.config.ts
を開き、次のコードを追加する。
export default defineNuxtConfig({
+ srcDir: "src/",
app: {
head: {
charset: "utf-16",
viewport: "width=device-width",
link: [{ rel: "icon", type: "image/x-icon", href: "/icon.png" }],
htmlAttrs: {
lang: "ja",
},
meta: [
{ property: "og:image", content: "/ogimage.png" },
{ property: "theme-color", content: "#1d94bb" },
],
},
},
})
これで、Tauri上でNuxt3が動作するようになった。
Tauriを起動する
ここまではTauri上にNuxt3を構築していった。最終的に起動するかどうかを確認する。
ルートディレクトリに戻って、
npm run tauri:dev
を実行する。Tauriのウィンドウが開いたら成功。
Tauriのウィンドウ配置を変更する
デフォルトではウィンドウ配置がランダムに行われ、ウィンドウ内コンテンツが見づらくなる恐れがあるので起動時にウィンドウを中央に配置するようにする。
tauri-plugin-positioner
というプラグインを用いてこれを行う。
注意として、TauriのページにあるTauri Plugin PositionerはTauri v2(ベータ)にしか対応していないため情報を調べる際は除外することをお勧めする。
Githubにある通りに進めると、positionerが動作しないのでここに修正版を載せておく。
まずは、src-tauriフォルダ内のCargo.toml
を開き、次のテキストを追加する。
[package]
name = "tauri-app"
version = "0.0.0"
description = "A Tauri App"
authors = ["you"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1", features = [] }
[dependencies]
tauri = { version = "1", features = ["shell-open"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# 次の一行を追加
tauri-plugin-positioner = { version = "1.0", features = ["system-tray"] }
[features]
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"]
次に、src-tauri/src内にあるmain.rs
を開き、次のように書き換える。このコードはGithub Copilot(Chat GPT)に一部書き換えをお願いしたが問題なく実行できた。
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri::Manager;
use tauri_plugin_positioner::{WindowExt, Position};
#[tauri::command]
fn main() {
let app = tauri::Builder::default()
.plugin(tauri_plugin_positioner::init())
// This is required to get tray-relative positions to work
.on_system_tray_event(|app, event| {
tauri_plugin_positioner::on_tray_event(app, &event);
})
.build(tauri::generate_context!())
.expect("error while building tauri application");
let win = app.get_window("main").unwrap();
let _ = win.move_window(Position::Center);
app.run(|_app_handle, _event| {});
}
この場合は、アプリ起動時・システムトレイ復帰時に中央にウィンドウを移動して表示させることができる。別の場所(左上など)に表示させたい場合は、let _ = win.move_window(Position::Center);
のPosition::の後を次のサイトのVariantsから選んで書き直す。
今回は、Rust側で管理する方法にしたが、Nuxt3側からの変更もできるはず。
デスクトップ開発
あとは、tauri:devを起動してNuxt3のvueファイルを編集するだけである。ホットリロード機能がついているので保存するとすぐにウィンドウに反映される。
また、ファイルを開くなどの動作を行う場合は、src-tauri/srcにrsファイルを作り、IPC Tunnelを作ってフロントエンド側と同期する。その際は、tauri.config.json
のallowlistに必要な権限を入れておく必要がある。
参考文献
- TauriにVueフレームワークのNuxt3を導入するまで(ついでにTailwindcssとRome) on Qiita
- Tauri window position 'Tray position not set' on StackOverflow
- Tauri Plugin Positioner(ここに書かれていることをそのまま使えないので注意)