From 22e0682f1059b6876571a8bf07c2168b0066728b Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Sun, 25 May 2025 17:42:12 +0100 Subject: [PATCH] fix hot-reload watcher for client/server (#4200) * use `@` syntax * watch the server * fmt --- packages/cli/src/cli/target.rs | 4 +- packages/cli/src/serve/runner.rs | 32 ++++++++++++++ packages/dioxus/src/launch.rs | 2 +- packages/dioxus/src/lib.rs | 76 ++++++++++++++++++-------------- packages/server/src/launch.rs | 7 ++- packages/server/src/lib.rs | 2 +- 6 files changed, 84 insertions(+), 39 deletions(-) diff --git a/packages/cli/src/cli/target.rs b/packages/cli/src/cli/target.rs index abfe382c5..d4e3b5d39 100644 --- a/packages/cli/src/cli/target.rs +++ b/packages/cli/src/cli/target.rs @@ -97,11 +97,11 @@ pub(crate) struct TargetArgs { #[command(subcommand_precedence_over_arg = true)] pub(crate) enum TargetCmd { /// Specify the arguments for the client build - #[clap(name = "client")] + #[clap(name = "@client")] Client(ChainedCommand), /// Specify the arguments for the server build - #[clap(name = "server")] + #[clap(name = "@server")] Server(ChainedCommand), } diff --git a/packages/cli/src/serve/runner.rs b/packages/cli/src/serve/runner.rs index 7b22b8bb8..fc5331800 100644 --- a/packages/cli/src/serve/runner.rs +++ b/packages/cli/src/serve/runner.rs @@ -777,6 +777,10 @@ impl AppServer { fn load_rsx_filemap(&mut self) { self.fill_filemap_from_krate(self.client.build.crate_dir()); + if let Some(server) = self.server.as_ref() { + self.fill_filemap_from_krate(server.build.crate_dir()); + } + for krate in self.all_watched_crates() { self.fill_filemap_from_krate(krate); } @@ -847,6 +851,17 @@ impl AppServer { } } + if let Some(server) = self.server.as_ref() { + // Watch the server's crate directory as well + for path in self.watch_paths(server.build.crate_dir(), server.build.crate_package) { + tracing::trace!("Watching path {path:?}"); + + if let Err(err) = self.watcher.watch(&path, RecursiveMode::Recursive) { + handle_notify_error(err); + } + } + } + // Also watch the crates themselves, but not recursively, such that we can pick up new folders for krate in self.all_watched_crates() { tracing::trace!("Watching path {krate:?}"); @@ -957,6 +972,23 @@ impl AppServer { .chain(Some(crate_dir)) .collect(); + if let Some(server) = self.server.as_ref() { + let server_crate_package = server.build.crate_package; + let server_crate_dir = server.build.crate_dir(); + + let server_krates: Vec = self + .local_dependencies(server_crate_package) + .into_iter() + .map(|p| { + p.parent() + .expect("Server manifest to exist and have a parent") + .to_path_buf() + }) + .chain(Some(server_crate_dir)) + .collect(); + krates.extend(server_krates); + } + krates.dedup(); krates diff --git a/packages/dioxus/src/launch.rs b/packages/dioxus/src/launch.rs index cb9b8c08d..87d755109 100644 --- a/packages/dioxus/src/launch.rs +++ b/packages/dioxus/src/launch.rs @@ -342,7 +342,7 @@ impl LaunchBuilder { #[cfg(feature = "server")] if matches!(platform, KnownPlatform::Server) { - return dioxus_server::launch(app, contexts, configs); + return dioxus_server::launch_cfg(app, contexts, configs); } #[cfg(feature = "web")] diff --git a/packages/dioxus/src/lib.rs b/packages/dioxus/src/lib.rs index 31a441306..f14b72b81 100644 --- a/packages/dioxus/src/lib.rs +++ b/packages/dioxus/src/lib.rs @@ -74,6 +74,48 @@ pub use dioxus_logger as logger; #[cfg_attr(docsrs, doc(cfg(feature = "cli-config")))] pub use dioxus_cli_config as cli_config; +#[cfg(feature = "server")] +#[cfg_attr(docsrs, doc(cfg(feature = "server")))] +pub use dioxus_server as server; + +#[cfg(feature = "devtools")] +#[cfg_attr(docsrs, doc(cfg(feature = "devtools")))] +pub use dioxus_devtools as devtools; + +#[cfg(feature = "web")] +#[cfg_attr(docsrs, doc(cfg(feature = "web")))] +pub use dioxus_web as web; + +#[cfg(feature = "router")] +#[cfg_attr(docsrs, doc(cfg(feature = "router")))] +pub use dioxus_router as router; + +#[cfg(feature = "fullstack")] +#[cfg_attr(docsrs, doc(cfg(feature = "fullstack")))] +pub use dioxus_fullstack as fullstack; + +#[cfg(feature = "desktop")] +#[cfg_attr(docsrs, doc(cfg(feature = "desktop")))] +pub use dioxus_desktop as desktop; + +#[cfg(feature = "mobile")] +#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))] +pub use dioxus_mobile as mobile; + +#[cfg(feature = "liveview")] +#[cfg_attr(docsrs, doc(cfg(feature = "liveview")))] +pub use dioxus_liveview as liveview; + +#[cfg(feature = "ssr")] +#[cfg_attr(docsrs, doc(cfg(feature = "ssr")))] +pub use dioxus_ssr as ssr; + +#[cfg(feature = "warnings")] +#[cfg_attr(docsrs, doc(cfg(feature = "warnings")))] +pub use warnings; + +pub use dioxus_config_macros as config_macros; + #[cfg(feature = "wasm-split")] #[cfg_attr(docsrs, doc(cfg(feature = "wasm-split")))] pub use wasm_splitter as wasm_split; @@ -146,37 +188,3 @@ pub mod prelude { #[cfg_attr(docsrs, doc(cfg(feature = "wasm-split")))] pub use wasm_splitter as wasm_split; } - -#[cfg(feature = "web")] -#[cfg_attr(docsrs, doc(cfg(feature = "web")))] -pub use dioxus_web as web; - -#[cfg(feature = "router")] -#[cfg_attr(docsrs, doc(cfg(feature = "router")))] -pub use dioxus_router as router; - -#[cfg(feature = "fullstack")] -#[cfg_attr(docsrs, doc(cfg(feature = "fullstack")))] -pub use dioxus_fullstack as fullstack; - -#[cfg(feature = "desktop")] -#[cfg_attr(docsrs, doc(cfg(feature = "desktop")))] -pub use dioxus_desktop as desktop; - -#[cfg(feature = "mobile")] -#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))] -pub use dioxus_mobile as mobile; - -#[cfg(feature = "liveview")] -#[cfg_attr(docsrs, doc(cfg(feature = "liveview")))] -pub use dioxus_liveview as liveview; - -#[cfg(feature = "ssr")] -#[cfg_attr(docsrs, doc(cfg(feature = "ssr")))] -pub use dioxus_ssr as ssr; - -#[cfg(feature = "warnings")] -#[cfg_attr(docsrs, doc(cfg(feature = "warnings")))] -pub use warnings; - -pub use dioxus_config_macros as config_macros; diff --git a/packages/server/src/launch.rs b/packages/server/src/launch.rs index d4dc6cebc..07db84293 100644 --- a/packages/server/src/launch.rs +++ b/packages/server/src/launch.rs @@ -30,9 +30,14 @@ type ContextList = Vec Box + Send + Sync>>; type BaseComp = fn() -> Element; +/// Launch a fullstack app with the given root component. +pub fn launch(root: BaseComp) -> ! { + launch_cfg(root, vec![], vec![]) +} + /// Launch a fullstack app with the given root component, contexts, and config. #[allow(unused)] -pub fn launch(root: BaseComp, contexts: ContextList, platform_config: Vec>) -> ! { +pub fn launch_cfg(root: BaseComp, contexts: ContextList, platform_config: Vec>) -> ! { #[cfg(not(target_arch = "wasm32"))] tokio::runtime::Runtime::new() .unwrap() diff --git a/packages/server/src/lib.rs b/packages/server/src/lib.rs index e2e264944..723ff4866 100644 --- a/packages/server/src/lib.rs +++ b/packages/server/src/lib.rs @@ -80,7 +80,7 @@ pub use document::ServerDocument; mod launch; #[cfg(not(target_arch = "wasm32"))] -pub use launch::launch; +pub use launch::{launch, launch_cfg}; /// Re-export commonly used items pub mod prelude {