tauri icon indicating copy to clipboard operation
tauri copied to clipboard

[bug] [V2] Node single executable binary works in Dev but not Production

Open mattma opened this issue 1 year ago • 1 comments

Describe the bug

Use @yao-pkg/pkg package to build a Node single executable binary via pkg -t node22-macos-arm64 -o express-server main.js, so that my Tauri app depends on when I ship to a MacOS app.

I moved the binary express-server to my-app/src-tauri/binaries folder, the full path is my-app/src-tauri/binaries/express-server.

Updated my-app/src-tauri/tauri.conf.json resources property so it can be properly bundled

{
...,
  "bundle": {
    ...,
    "resources": [
      "binaries"
    ]
  }
}

Here is my my-app/src-tauri/src/main.rs, I want to start up the Node Express Server whenever I run tauri dev or tauri build for bundling and releasing the MacOS app.

use std::process::{Command};
use std::env;
use tauri::command;
use std::error::Error;
use tauri_plugin_shell::{ShellExt, process::CommandEvent};
use tauri::{path::BaseDirectory, App, Manager};

// Function to spawn the Express server
fn start_server(app: &App) -> Result<(), Box<dyn Error>> {
    let express_server = app.path().resolve("binaries/express-server", BaseDirectory::Resource)?;

    println!("express_server {}", express_server.display());
 
    let output = tauri::async_runtime::block_on(async move {
        Command::new(express_server)
            .spawn()
            .expect("Failed to start Express server");
    });

    Ok(())
}

fn main() {
    tauri::Builder::default()
        .plugin(tauri_plugin_shell::init())
        .plugin(tauri_plugin_fs::init())
        .invoke_handler(tauri::generate_handler![some_command])
        .setup(|app| {
            // Run the Express server based on environment
            if let Err(err) = start_server(&app) {
                eprintln!("Failed to start Express server: {}", err);
            }

            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Everything works fine in tauri dev, Express server runs as expected. But it does not work for bundling after i run tauri build.

The dmg is being generated at my-app/src-tauri/target/release/bundle/dmg/my-app-express. the express server binary path is my-app/src-tauri/target/release/binaries/express-server.

When I click on my-app.dmg, then right click on my-app.app, select show package contents, then I can see a folder of Contents/Resources/binaries/express-server. When i run my-app.app, the Express server does not start, I run lsof -i:8080, the port 8080 is my express server port, the process does not start.

Can someone help me understand why?

I am a new to Rust, if you could provide some code example, that would be great.

As a bonus question, when I close my-app.app or kill tauri dev in the local development, how can I probably shutdown the Express server? Thanks in advance!

Reproduction

No response

Expected behavior

No response

Full tauri info output

[✔] Environment
    - OS: Mac OS 14.6.1 arm64 (X64)
    ✔ Xcode Command Line Tools: installed
    ✔ rustc: 1.78.0 (9b00956e5 2024-04-29)
    ✔ cargo: 1.78.0 (54d8815d0 2024-03-26)
    ✔ rustup: 1.27.1 (54dd3d00f 2024-04-24)
    ✔ Rust toolchain: stable-aarch64-apple-darwin (default)
    - node: 22.2.0
    - pnpm: 9.12.0
    - yarn: 1.22.21
    - npm: 10.7.0

[-] Packages
    - tauri 🦀: 2.0.2
    - tauri-build 🦀: 2.0.1
    - wry 🦀: 0.44.1
    - tao 🦀: 0.30.3
    - @tauri-apps/api : 2.0.1 (outdated, latest: 2.0.2)
    - @tauri-apps/cli : 2.0.1 (outdated, latest: 2.0.2)

[-] Plugins
    - tauri-plugin-cli 🦀: 2.0.1
    - @tauri-apps/plugin-cli : not installed!
    - tauri-plugin-fs 🦀: 2.0.1
    - @tauri-apps/plugin-fs : not installed!
    - tauri-plugin-shell 🦀: 2.0.1
    - @tauri-apps/plugin-shell : 2.0.0

[-] App
    - build-type: bundle
    - CSP: unset
    - frontendDist: ../dist
    - devUrl: http://localhost:3000/
    - framework: React (Next.js)
    - bundler: Webpack

Stack trace

No response

Additional context

No response

mattma avatar Oct 07 '24 21:10 mattma

When i run my-app.app, the Express server does not start

Did you also try starting the app binary in the app bundle directly from inside a terminal? I hope it gives some kind of info at least. If that doesn't give more info, did you try writing the logs/errors to a file instead of stdout?

Is there any reason you bundle it as a resource instead of a sidecar (externalBin)? Knowing macOS i wouldn't be surprised if the file location in the bundle would matter.

As a bonus question, when I close my-app.app or kill tauri dev in the local development, how can I probably shutdown the Express server? Thanks in advance!

To do that reliably, or at all if it should also work for tauri dev, you need to do that in your server binary by checking if its parent process still exists (i don't have an example at hand). For "normal" uses, killing the command chil in the Exit or ExitRequested events in your tauri app should work though.

FabianLars avatar Oct 17 '24 20:10 FabianLars

Following your advice, I write the logs to a file. Clearly, the error is not related to Tauri. Thanks again for the advice.

mattma avatar Nov 02 '24 19:11 mattma

How to fix it? my binary is on "externalBin": ["bin/api/main"], work in dev but not in production, when i look to content package, it placed in root folder not bin/api/main

lutfi-haslab avatar Feb 11 '25 11:02 lutfi-haslab