[bug] [V2] Node single executable binary works in Dev but not Production
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
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.
Following your advice, I write the logs to a file. Clearly, the error is not related to Tauri. Thanks again for the advice.
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