Bundled fullstack desktop apps don't work (Linux, Windows)
Problem
I simply create a fullstack app with dx new, bundle it with dx bundle --platform desktop on Linux and Windows. Neither the Linux AppImage nor Windows MSI nor Windows Setup work.
Steps To Reproduce
Steps to reproduce the behavior:
dx new some_app, choose fullstack.dx bundle --platform desktop(Linux, Windows)- Start the AppImage on Linux, or install via MSI or Setup on Windows
Expected behavior
- I expect the assets to be found and the app to run, i.e. the echo demo should work
Actual behavior:
- Linux: Assets arent't found, echo demo panics with
called `Result::unwrap()` on an `Err` value: Request("error sending request for url (http://127.0.0.1:8080/api/echo_server10415857101433548226)")
- Windows: App doesn't even launch, panics with
called `Result::unwrap()` on an `Err` value: Os { code: 10048, kind: AddrInUse, message: "Normalerweise darf jede Socketadresse (Protokoll, Netzwerkadresse oder Anschluss) nur jeweils einmal verwendet werden." }
(Sorry, my Windows is German, but AddrInUse should be clear.)
Environment:
- Dioxus version: 0.6.2
- Rust version: 1.83.0
- OS info: Ubuntu 24.04 / Windows 11
- App platform:
desktop
There is probably a lot I can configure in Dioxus.toml, but the documentation is somewhat scattered, the bundle sections are unclear to me, also I'm not sure how to write my main function properly. Currently it looks like this, I'm still toying around:
fn main() {
LaunchBuilder::new()
.with_cfg(desktop! {
println!("cfg desktop");
if cfg!(target_os = "windows") {
// Someone said this should work on Windows, but I haven't tested it yet because the app panics early
let data_dir = std::env::var("LOCALAPPDATA").expect("env var LOCALAPPDATA not found");
dioxus::desktop::Config::default().with_data_directory(data_dir)
} else {
dioxus::desktop::Config::default()
}
})
.with_cfg(server_only! {
println!("cfg server_only");
ServeConfigBuilder::default()
})
.with_cfg(web! {
println!("cfg web");
WebConfigBuilder::default()
})
.launch(App);
}
#3693 should fix the CLI issue that was causing two server builds to be bundled instead of a server and desktop build.
I'm not sure how to write my main function properly. Currently it looks like this, I'm still toying around
You need to set the production url of your server in your main.rs so it doesn't try to connect to localhost:
// Set the url of the server where server functions are hosted.
#[cfg(not(feature = "server"))]
dioxus::fullstack::prelude::server_fn::client::set_server_url("http://yourserverlocation");
^ That snippet is taken from the fullstack desktop example
Okay, I added this line, copied from the example:
#[cfg(not(feature = "server"))]
server_fn::client::set_server_url("http://127.0.0.1:8080");
This is a small step forward. Now, the echo server function works via dx serve --platform desktop, which it didn't before.
But I don't want to use port 8080 all the time---how could I ever have more than one instance of my app? And in production (bundles), I want to choose a random free port and not worry about it at all, of course. How would I set up this?
Server functions don't work when the app is run through a bundled AppImage. Typing something to echo results in
2025-02-05T09:40:27.217552Z DEBUG hyper_util::client::legacy::connect::http: connecting to 127.0.0.1:8080
thread 'main' panicked at src/components/echo.rs:18:65:
called `Result::unwrap()` on an `Err` value: Request("error sending request for url (http://127.0.0.1:8080/api/echo_server10415857101433548226)")
After you bundle the app with the CLI from https://github.com/DioxusLabs/dioxus/pull/3693, you need to run both the server bundle and the desktop app seperately. The CLI should print the location of both near the end of the logs.
If you want to change the port or IP the server is hosted on, you can set the PORT and IP environment variables before you run the bundled server and change the url you pass to set_server_url
So I will have to wait for a new release then? Will I still be able to simply say dx run or dx serve?
I noticed there is some default setup in Dioxus' launch.rs, setting the server URL to 127.0.0.1:<PORT>. Shouldn't this work out of the box?
PORT and IP variables are confusing. On dx run, IP is set to "127.0.0.1", and PORT to "8080". On dx serve, IP is set to "172.28.[...]", PORT is set to "42197" (random), though the CLI says server functions are at 8080. And for the AppImage, neither of the two variables are set, and server functions never work.
So I will have to wait for a new release then? Will I still be able to simply say
dx runordx serve?I noticed there is some default setup in Dioxus'
launch.rs, setting the server URL to 127.0.0.1:. Shouldn't this work out of the box?
#3701 fixes serving with dx serve if you don't set the server url manually. If you set the server url manually, it should work today
PORT and IP variables are confusing. On
dx run, IP is set to "127.0.0.1", and PORT to "8080". Ondx serve, IP is set to "172.28.[...]", PORT is set to "42197" (random), though the CLI says server functions are at 8080. And for the AppImage, neither of the two variables are set, and server functions never work.
You will always need to set the server url manually with set_server_url and run the server manually in production builds. The desktop app running on someones device doesn't know where the server is if you don't set it manaully
On android setting the production url results in Deserialization error, and setting it to just http://127.0.0.1:8080 with emulator results in:
02-06 16:27:37.139 4174 4248 I RustStdoutStderr: called `Result::unwrap()` on an `Err` value: Request("error sending request for url (http://127.0.0.1:8080/api/fetch_session_info785665823974837370)")
as well. And that is using both the git version and released one.
What do you mean with "production build"---a bundled app I create with dx bundle? How would I configure and run the server manually?
@phkoester not sure if it's still relevant, but I faced similar issue when trying to create just a simple desktop application. Eventually, my understanding is that a simple desktop app is not fullstack, it's just desktop. the full stack is for case when you want a server and client apps connecting to it. At least that's my understanding but I'm just starting with this.
@phkoester not sure if it's still relevant, but I faced similar issue when trying to create just a simple desktop application. Eventually, my understanding is that a simple desktop app is not fullstack, it's just desktop. the full stack is for case when you want a server and client apps connecting to it. At least that's my understanding but I'm just starting with this.
@yanshay - Should we be using a different term (other than "fullstack") for a desktop or mobile binary that has a backend (for instance, creating it's own sqlite db on the desktop/mobile device to persist structured data) but where that backend isn't managed by a separate server binary?
I'm looking at the example desktop projects like the file explorer but none of them store their own structured data.
@phkoester not sure if it's still relevant, but I faced similar issue when trying to create just a simple desktop application. Eventually, my understanding is that a simple desktop app is not fullstack, it's just desktop. the full stack is for case when you want a server and client apps connecting to it. At least that's my understanding but I'm just starting with this.
@yanshay - Should we be using a different term (other than "fullstack") for a desktop or mobile binary that has a backend (for instance, creating it's own sqlite db on the desktop/mobile device to persist structured data) but where that backend isn't managed by a separate server binary?
I'm looking at the example desktop projects like the file explorer but none of them store their own structured data.
I'm not sure if the terminology is critical, I think the documentation of what each term mean and possible combinations should be clearer. Even now searching for such one page on that I can't find such. It assumes everyone knows what each term means, and the architecture, but I for example thought that the Desktop is just a browser in a desktop app, and need the full-stack part to gain access to the file system.
This is how I think of these: There's Web vs. Desktop, and then there's FullStack option which is an add-on to either. And while Web doesn't have access to any machine resources, Desktop has full access to the machine it's running on. FullStack is the add-on for having a built-in communication channel + server code + maybe more (ssg), interleaved with client code - from either Web or Desktop to another server.
So I think a document, very early in the documentation on the high level architecture and the terms is in place.