開発サーバーの起動とデバッグ

npm run tauri dev が Vite の起動から Rust の再ビルドまで何をしているかと、WebView の開発者ツール、Rust のログとデバッガーの使い方、ポート 1420 が使用中のときの直し方を示す。

環境構築 対象: Tauri 2.x 更新日: 読了目安: 約8分 env-010
目次
  1. 前提条件
  2. 1. tauri dev の中で起きていること
  3. 2. WebView の開発者ツール
  4. 3. Rust のログとデバッガー
  5. 4. ポートの衝突を直す
  6. 動作確認
  7. よくあるエラーと対処法
  8. OS ごとの違いと注意点
  9. 関連レシピ

開発中は npm run tauri dev 1 つで、Vite の起動、Rust のビルド、ウィンドウの表示、変更の監視までが行われます。便利な反面、止まったときに「Vite か、Rust か、設定か」が分かりにくくなります。tauri dev の流れと、フロントエンドは開発者ツール、Rust はログとデバッガーで調べる方法、ポートの衝突の直し方をまとめます。

前提条件

create-tauri-app で作ったプロジェクトで npm install を済ませておきます。tauri dev が読む devUrl と beforeDevCommand は tauri.conf.json の基本設定 で説明しています。開発者ツールのショートカットは権限 core:webview:allow-internal-toggle-devtools で動き、core:default に含まれるので追加は不要です。

1. tauri dev の中で起きていること

  1. beforeDevCommand(npm run dev)で Vite がポート 1420 で起動する
  2. devUrl に接続できるまで待つ(長引くと「Waiting for your frontend dev server to start on …」と出る)
  3. Rust をデバッグビルドする。初回は依存クレートのコンパイルで数分かかる
  4. アプリが起動し、WebView が devUrl のページを読む
  5. 以降はファイルの変更を監視する

止まったらターミナルの最後の行でどの段階かを判断します。変更への反応は、src/ と src-tauri/ のどちらを触ったかで決まります(Tauri プロジェクトのディレクトリ構成)。

変更したもの起きること
src/ の TS・CSS、index.htmlVite が画面を差し替える。アプリは再起動しない
src-tauri/src/*.rs「File … changed. Rebuilding application...」と出て再ビルドし、アプリを再起動する
tauri.conf.json・capabilities/同じく再ビルドして再起動する

再起動では JS の変数も Rust の State も初期化されます。状態を保ったまま調べたいときは npm run tauri dev -- --no-watch で監視を止めます。

アプリ自身が src-tauri/ にファイルを書くと、変更と見なされて再起動を繰り返します。開発中はカレントディレクトリが src-tauri/ なので、相対パスで書くとここにできます。保存先をアプリデータのフォルダにするか、src-tauri/.taurignore に .gitignore と同じ書式で除外を書きます。

*.db
logs/

2. WebView の開発者ツール

Windows / Linux は Ctrl+Shift+I、macOS は Cmd+Option+I で開閉でき、右クリックの「検証」(Inspect)でも開けます。使えるのはデバッグビルド(tauri dev と tauri build --debug)だけで、リリースビルドで使う方法やコードから開く方法は 開発者ツールをプログラムから開く にあります。

便利なのは Network タブで invoke の中身を見られる ことです。呼び出しは Windows では http://ipc.localhost/greet、macOS / Linux では ipc://localhost/greet への POST として並び、引数と戻り値が見えるので、Rust に届いていないのか、Rust がエラーを返したのかを切り分けられます。

3. Rust のログとデバッガー

println! / eprintln! の出力は tauri dev を実行したターミナルに出ます。開発中だけ動かす処理は tauri::is_dev()(tauri dev で起動したとき true)か #[cfg(debug_assertions)](tauri build --debug でも有効)で囲みます。

use tauri::Manager;

#[tauri::command]
fn read_note(path: String) -> Result<String, String> {
    eprintln!("[read_note] path = {path}"); // tauri dev のターミナルに出る
    std::fs::read_to_string(&path).map_err(|e| {
        eprintln!("[read_note] failed: {e:?}"); // Debug 表示なら OS のエラーコードまで出る
        e.to_string()
    })
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            if tauri::is_dev() {
                println!("app data = {:?}", app.path().app_data_dir()?);
            }
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![read_note])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

パニックで落ちたときは、環境変数 RUST_BACKTRACE=1 を付けて起動すると落ちた場所まで表示されます。

$env:RUST_BACKTRACE = 1; npm run tauri dev
RUST_BACKTRACE=1 npm run tauri dev

ブレークポイントで止めたいときは VS Code のデバッガーから Cargo を直接起動します(VS Code 拡張機能の推奨設定)。この方法では変更監視が働かず、Vite も別に起動しておく必要があります。Windows のリリースビルドはコンソールを開かないので、配布後のログは Log プラグイン でファイルに残します。

4. ポートの衝突を直す

前回の Vite が残っているか、別の Tauri プロジェクトを同時に動かしていると次のように止まります(テンプレートはどれも 1420 を使います)。

error when starting dev server:
Error: Port 1420 is already in use

続いて「The "beforeDevCommand" terminated with a non-zero status code.」と出て終了します。使っているプロセスを探して止めます。

Get-NetTCPConnection -LocalPort 1420 -State Listen | Select-Object OwningProcess
Stop-Process -Id 12345   # 上で表示された番号
lsof -i :1420   # macOS / Linux。PID 列の番号を確認
kill 12345

2 つのプロジェクトを並行して動かすなら、片方の vite.config.ts の server.port と tauri.conf.json の build.devUrl を両方変えます。

import { defineConfig } from 'vite';

export default defineConfig({
  clearScreen: false, // Rust のエラーが Vite の画面消去で流れないように
  server: {
    port: 1425, // tauri.conf.json の devUrl と同じ番号にする
    strictPort: true, // 使用中なら別の番号に逃げずにエラーで止まる
    watch: { ignored: ['**/src-tauri/**'] },
  },
});
{
  "build": { "devUrl": "http://localhost:1425" }
}

strictPort: true は外しません。外すと Vite は別の番号に逃げますが、Tauri は devUrl の 1420 を読み続けるので、もう一方のプロジェクトの画面が表示されます。

動作確認

npm run tauri dev を実行し、次の順に確かめます。

  1. Vite の「Local: http://localhost:1420/」の後に Rust のコンパイルが進み、ウィンドウが開く
  2. src/main.ts を保存すると、アプリは再起動せずに画面だけ変わる
  3. lib.rs を保存すると「Rebuilding application...」と出てアプリが再起動する
  4. Ctrl+Shift+I で開発者ツールが開き、Greet を押すと Network タブに greet が出る
  5. read_note に存在しないパスを渡すと、ターミナルに次のように出る(日本語版 Windows の例)
[read_note] path = C:\nope.txt
[read_note] failed: Os { code: 2, kind: NotFound, message: "指定されたファイルが見つかりません。" }

よくあるエラーと対処法

  • 「Waiting for your frontend dev server to start on …」が続き、「Please make sure that is the URL to your dev server.」で終わる: Vite が起動に失敗したか、devUrl と違うポートで動いています。上に流れた Vite のエラーと、server.port と devUrl の一致を確かめます。
  • ウィンドウが真っ白、または接続できないというページになる: src-tauri で cargo run を実行したか、デバッガーから起動して Vite が動いていません。デバッグビルドは常に devUrl を読みに行きます。
  • サブウィンドウだけ Ctrl+Shift+I が効かない: そのウィンドウのラベルが、core:default を含む capability の windows に入っていません。右クリックの「検証」なら開けます。
  • 保存するたびに再起動が止まらない: アプリが src-tauri/ にファイルを書いています。1 章の .taurignore で除外します。

OS ごとの違いと注意点

  • Windows: 開発者ツールは Microsoft Edge の DevTools が別ウィンドウで開きます。Hyper-V や WSL の予約ポート範囲に 1420 が入ると、使用中のプロセスが無くても起動できない(EACCES を含むエラー)ことがあり、netsh interface ipv4 show excludedportrange protocol=tcp で確認できます。
  • macOS: Safari の Web インスペクターが開きます。
  • Linux: WebKit の Web インスペクターが開きます。
  • Android / iOS: npm run tauri android dev(iOS は ios dev)で起動します。開発者ツールはアプリ内では開けず、Android はパソコンの Chrome の chrome://inspect/#devices、iOS は Mac の Safari の「開発」メニューからつなぎます。

関連レシピ

参考リンク(公式ドキュメント)

Web Ninja

この記事を書いた人

Web Ninja ウェブエンジニア (Web Engineer)

会社員ネットワークエンジニアから独立してかれこれ 25 年以上 Web エンジニアとして活動中。普段は JavaScript と Node.js を自在に操り、時には C++ や Perl といった古流の技も嗜みます。近年は Tauri × Rust という新たな武器を手に、デスクトップアプリ開発の最前線を駆け抜けています。「作りたい」を「作れる」に変えるための、実践的な「技」をお届けします。

お問い合わせ: tauri.ninja@gmail.com

内容の誤り・動かないコードを報告する