diff --git a/Cargo.lock b/Cargo.lock index 41d9f8eb5..abf1ce3a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -722,6 +722,7 @@ dependencies = [ "log", "mlua", "notify", + "open", "proc-macro2", "regex", "reqwest", @@ -1521,6 +1522,25 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + [[package]] name = "is_executable" version = "0.1.2" @@ -1898,6 +1918,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "open" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16814a067484415fda653868c9be0ac5f2abd2ef5d951082a5f2fe1b3662944" +dependencies = [ + "is-wsl", + "pathdiff", +] + [[package]] name = "openssl" version = "0.10.45" @@ -1992,6 +2022,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "pbkdf2" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 45539252c..9219db5ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,7 @@ dioxus-html = { version = "0.3", features = ["hot-reload-context"] } dioxus-core = { version = "0.3", features = ["serialize"] } dioxus-autofmt = "0.3.0" rsx-rosetta = { version = "0.3" } +open = "4.1.0" [[bin]] path = "src/main.rs" diff --git a/docs/src/cmd/serve.md b/docs/src/cmd/serve.md index 4a699267b..2e24cb3f7 100644 --- a/docs/src/cmd/serve.md +++ b/docs/src/cmd/serve.md @@ -45,5 +45,13 @@ You can use `--example {name}` to start a example code. ``` # build `example/test` code -dioxus serve --example test +dioxus serve --exmaple test +``` + +## Open Browser + +You can add `--open` flag to open system default browser when server startup. + +``` +dioxus serve --open ``` diff --git a/src/cli/cfg.rs b/src/cli/cfg.rs index 9fe453c49..ee6284ac1 100644 --- a/src/cli/cfg.rs +++ b/src/cli/cfg.rs @@ -45,6 +45,11 @@ pub struct ConfigOptsServe { #[clap(default_value_t = 8080)] pub port: u16, + /// Open the app in the default browser [default: false] + #[clap(long)] + #[serde(default)] + pub open: bool, + /// Build a example [default: ""] #[clap(long)] pub example: Option, diff --git a/src/cli/serve/mod.rs b/src/cli/serve/mod.rs index ce0dd743e..e3485c1f1 100644 --- a/src/cli/serve/mod.rs +++ b/src/cli/serve/mod.rs @@ -68,7 +68,7 @@ impl Serve { Serve::regen_dev_page(&crate_config)?; // start the develop server - server::startup(self.serve.port, crate_config.clone()).await?; + server::startup(self.serve.port, crate_config.clone(), self.serve.open).await?; Ok(()) } diff --git a/src/server/mod.rs b/src/server/mod.rs index 42622466b..6daf7e289 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -55,7 +55,7 @@ struct WsReloadState { update: broadcast::Sender<()>, } -pub async fn startup(port: u16, config: CrateConfig) -> Result<()> { +pub async fn startup(port: u16, config: CrateConfig, start_browser: bool) -> Result<()> { // ctrl-c shutdown checker let crate_config = config.clone(); let _ = ctrlc::set_handler(move || { @@ -64,10 +64,11 @@ pub async fn startup(port: u16, config: CrateConfig) -> Result<()> { }); let ip = get_ip().unwrap_or(String::from("0.0.0.0")); + if config.hot_reload { - startup_hot_reload(ip, port, config).await? + startup_hot_reload(ip, port, config, start_browser).await? } else { - startup_default(ip, port, config).await? + startup_default(ip, port, config, start_browser).await? } Ok(()) } @@ -129,7 +130,7 @@ pub async fn hot_reload_handler( } #[allow(unused_assignments)] -pub async fn startup_hot_reload(ip: String, port: u16, config: CrateConfig) -> Result<()> { +pub async fn startup_hot_reload(ip: String, port: u16, config: CrateConfig, start_browser: bool) -> Result<()> { let first_build_result = crate::builder::build(&config, false)?; log::info!("🚀 Starting development server..."); @@ -319,14 +320,25 @@ pub async fn startup_hot_reload(ip: String, port: u16, config: CrateConfig) -> R .layer(Extension(ws_reload_state)) .layer(Extension(hot_reload_state)); - axum::Server::bind(&format!("0.0.0.0:{}", port).parse().unwrap()) - .serve(router.into_make_service()) - .await?; + let addr = format!("0.0.0.0:{}", port).parse().unwrap(); + + let server = axum::Server::bind(&addr).serve(router.into_make_service()); + + if start_browser { + let _ = open::that(format!("http://{}", addr)); + } + + server.await?; Ok(()) } -pub async fn startup_default(ip: String, port: u16, config: CrateConfig) -> Result<()> { +pub async fn startup_default( + ip: String, + port: u16, + config: CrateConfig, + start_browser: bool, +) -> Result<()> { let first_build_result = crate::builder::build(&config, false)?; log::info!("🚀 Starting development server..."); @@ -461,9 +473,14 @@ pub async fn startup_default(ip: String, port: u16, config: CrateConfig) -> Resu ) .layer(Extension(ws_reload_state)); - axum::Server::bind(&format!("0.0.0.0:{}", port).parse().unwrap()) - .serve(router.into_make_service()) - .await?; + let addr = format!("0.0.0.0:{}", port).parse().unwrap(); + let server = axum::Server::bind(&addr).serve(router.into_make_service()); + + if start_browser { + let _ = open::that(format!("http://{}", addr)); + } + + server.await?; Ok(()) }