fix desktop hot reloading
This commit is contained in:
1 parent
0c5025ffa0
commit
2c1c147828
15 files changed
+130
-115
No files matched your search
@@ -364,6 +364,7 @@ pub fn build_desktop(config: &CrateConfig, _is_serve: bool) -> Result<BuildResul
|
||||
.display()
|
||||
);
|
||||
}
|
||||
println!("build desktop done");
|
||||
|
||||
Ok(BuildResult {
|
||||
warnings: vec![],
|
||||
|
||||
@@ -57,21 +57,7 @@ impl Serve {
|
||||
.await?;
|
||||
}
|
||||
cfg::Platform::Desktop => {
|
||||
crate::builder::build_desktop(&crate_config, true)?;
|
||||
|
||||
match &crate_config.executable {
|
||||
crate::ExecutableType::Binary(name)
|
||||
| crate::ExecutableType::Lib(name)
|
||||
| crate::ExecutableType::Example(name) => {
|
||||
let mut file = crate_config.out_dir.join(name);
|
||||
if cfg!(windows) {
|
||||
file.set_extension("exe");
|
||||
}
|
||||
Command::new(file.to_str().unwrap())
|
||||
.stdout(Stdio::inherit())
|
||||
.output()?;
|
||||
}
|
||||
}
|
||||
server::desktop::startup(crate_config.clone()).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
serve::Serve,
|
||||
server::{
|
||||
output::{print_console_info, PrettierOptions, WebServerInfo},
|
||||
setup_file_watcher, setup_file_watcher_hot_reload, BuildManager,
|
||||
setup_file_watcher, setup_file_watcher_hot_reload,
|
||||
},
|
||||
BuildResult, CrateConfig, Result,
|
||||
};
|
||||
@@ -72,7 +72,15 @@ pub async fn serve_default(config: CrateConfig) -> Result<()> {
|
||||
|
||||
// We got to own watcher so that it exists for the duration of serve
|
||||
// Otherwise full reload won't work.
|
||||
let _watcher = setup_file_watcher(crate::cfg::Platform::Desktop, &config, None, None).await?;
|
||||
let _watcher = setup_file_watcher(
|
||||
{
|
||||
let config = config.clone();
|
||||
move || start_desktop(&config)
|
||||
},
|
||||
&config,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Print serve info
|
||||
print_console_info(
|
||||
@@ -107,15 +115,13 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> {
|
||||
}
|
||||
|
||||
let file_map = Arc::new(Mutex::new(map));
|
||||
let build_manager = Arc::new(BuildManager {
|
||||
platform: crate::cfg::Platform::Web,
|
||||
config: config.clone(),
|
||||
reload_tx: None,
|
||||
});
|
||||
|
||||
let (hot_reload_tx, mut hot_reload_rx) = broadcast::channel(100);
|
||||
|
||||
// States
|
||||
// The open interprocess sockets
|
||||
let channels = Arc::new(Mutex::new(Vec::new()));
|
||||
|
||||
// Setup file watcher
|
||||
// We got to own watcher so that it exists for the duration of serve
|
||||
// Otherwise hot reload won't work.
|
||||
@@ -123,7 +129,17 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> {
|
||||
&config,
|
||||
hot_reload_tx,
|
||||
file_map.clone(),
|
||||
build_manager,
|
||||
{
|
||||
let config = config.clone();
|
||||
|
||||
let channels = channels.clone();
|
||||
move || {
|
||||
for channel in &mut *channels.lock().unwrap() {
|
||||
send_msg(HotReloadMsg::Shutdown, channel);
|
||||
}
|
||||
start_desktop(&config)
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
@@ -153,8 +169,6 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let channels = Arc::new(Mutex::new(Vec::new()));
|
||||
|
||||
match LocalSocketListener::bind("@dioxusin") {
|
||||
Ok(local_socket_stream) => {
|
||||
let aborted = Arc::new(Mutex::new(false));
|
||||
@@ -196,10 +210,6 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> {
|
||||
}
|
||||
});
|
||||
|
||||
// for channel in &mut *channels.lock().unwrap() {
|
||||
// send_msg(HotReloadMsg::Shutdown, channel);
|
||||
// }
|
||||
|
||||
while let Ok(template) = hot_reload_rx.recv().await {
|
||||
let channels = &mut *channels.lock().unwrap();
|
||||
let mut i = 0;
|
||||
|
||||
@@ -39,18 +39,11 @@ pub mod desktop;
|
||||
pub mod web;
|
||||
|
||||
/// Sets up a file watcher
|
||||
async fn setup_file_watcher(
|
||||
platform: Platform,
|
||||
async fn setup_file_watcher<F: Fn() -> Result<BuildResult> + Send + 'static>(
|
||||
build_with: F,
|
||||
config: &CrateConfig,
|
||||
reload_tx: Option<Sender<()>>,
|
||||
web_info: Option<WebServerInfo>,
|
||||
) -> Result<RecommendedWatcher> {
|
||||
let build_manager = BuildManager {
|
||||
platform,
|
||||
config: config.clone(),
|
||||
reload_tx,
|
||||
};
|
||||
|
||||
let mut last_update_time = chrono::Local::now().timestamp();
|
||||
|
||||
// file watcher: check file change
|
||||
@@ -67,7 +60,7 @@ async fn setup_file_watcher(
|
||||
let config = watcher_config.clone();
|
||||
if let Ok(e) = info {
|
||||
if chrono::Local::now().timestamp() > last_update_time {
|
||||
match build_manager.rebuild() {
|
||||
match build_with() {
|
||||
Ok(res) => {
|
||||
last_update_time = chrono::Local::now().timestamp();
|
||||
|
||||
@@ -108,11 +101,11 @@ async fn setup_file_watcher(
|
||||
|
||||
// Todo: reduce duplication and merge with setup_file_watcher()
|
||||
/// Sets up a file watcher with hot reload
|
||||
async fn setup_file_watcher_hot_reload(
|
||||
async fn setup_file_watcher_hot_reload<F: Fn() -> Result<BuildResult> + Send + 'static>(
|
||||
config: &CrateConfig,
|
||||
hot_reload_tx: Sender<Template<'static>>,
|
||||
file_map: Arc<Mutex<FileMap<HtmlCtx>>>,
|
||||
build_manager: Arc<BuildManager>,
|
||||
build_with: F,
|
||||
web_info: Option<WebServerInfo>,
|
||||
) -> Result<RecommendedWatcher> {
|
||||
// file watcher: check file change
|
||||
@@ -138,7 +131,7 @@ async fn setup_file_watcher_hot_reload(
|
||||
for path in evt.paths.clone() {
|
||||
// if this is not a rust file, rebuild the whole project
|
||||
if path.extension().and_then(|p| p.to_str()) != Some("rs") {
|
||||
match build_manager.rebuild() {
|
||||
match build_with() {
|
||||
Ok(res) => {
|
||||
print_console_info(
|
||||
&config,
|
||||
@@ -164,7 +157,7 @@ async fn setup_file_watcher_hot_reload(
|
||||
messages.extend(msgs);
|
||||
}
|
||||
Ok(UpdateResult::NeedsRebuild) => {
|
||||
match build_manager.rebuild() {
|
||||
match build_with() {
|
||||
Ok(res) => {
|
||||
print_console_info(
|
||||
&config,
|
||||
@@ -209,35 +202,3 @@ async fn setup_file_watcher_hot_reload(
|
||||
|
||||
Ok(watcher)
|
||||
}
|
||||
|
||||
pub struct BuildManager {
|
||||
platform: Platform,
|
||||
config: CrateConfig,
|
||||
reload_tx: Option<broadcast::Sender<()>>,
|
||||
}
|
||||
|
||||
impl BuildManager {
|
||||
fn rebuild(&self) -> Result<BuildResult> {
|
||||
log::info!("🪁 Rebuild project");
|
||||
match self.platform {
|
||||
Platform::Web => {
|
||||
let result = builder::build(&self.config, true)?;
|
||||
// change the websocket reload state to true;
|
||||
// the page will auto-reload.
|
||||
if self
|
||||
.config
|
||||
.dioxus_config
|
||||
.web
|
||||
.watcher
|
||||
.reload_html
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let _ = Serve::regen_dev_page(&self.config);
|
||||
}
|
||||
let _ = self.reload_tx.as_ref().map(|tx| tx.send(()));
|
||||
Ok(result)
|
||||
}
|
||||
Platform::Desktop => start_desktop(&self.config),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,10 @@ use dioxus_html::HtmlCtx;
|
||||
use dioxus_rsx::hot_reload::FileMap;
|
||||
use tokio::sync::broadcast;
|
||||
|
||||
use super::BuildManager;
|
||||
use crate::CrateConfig;
|
||||
|
||||
pub struct HotReloadState {
|
||||
pub messages: broadcast::Sender<Template<'static>>,
|
||||
pub build_manager: Arc<BuildManager>,
|
||||
pub file_map: Arc<Mutex<FileMap<HtmlCtx>>>,
|
||||
pub watcher_config: CrateConfig,
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
serve::Serve,
|
||||
server::{
|
||||
output::{print_console_info, PrettierOptions, WebServerInfo},
|
||||
setup_file_watcher, setup_file_watcher_hot_reload, BuildManager,
|
||||
setup_file_watcher, setup_file_watcher_hot_reload,
|
||||
},
|
||||
BuildResult, CrateConfig, Result,
|
||||
};
|
||||
@@ -86,9 +86,12 @@ pub async fn serve_default(
|
||||
// We got to own watcher so that it exists for the duration of serve
|
||||
// Otherwise full reload won't work.
|
||||
let _watcher = setup_file_watcher(
|
||||
crate::cfg::Platform::Web,
|
||||
{
|
||||
let config = config.clone();
|
||||
let reload_tx = reload_tx.clone();
|
||||
move || build(&config, &reload_tx)
|
||||
},
|
||||
&config,
|
||||
Some(reload_tx.clone()),
|
||||
Some(WebServerInfo {
|
||||
ip: ip.clone(),
|
||||
port,
|
||||
@@ -148,18 +151,12 @@ pub async fn serve_hot_reload(
|
||||
}
|
||||
|
||||
let file_map = Arc::new(Mutex::new(map));
|
||||
let build_manager = Arc::new(BuildManager {
|
||||
platform: crate::cfg::Platform::Web,
|
||||
config: config.clone(),
|
||||
reload_tx: Some(reload_tx.clone()),
|
||||
});
|
||||
|
||||
let hot_reload_tx = broadcast::channel(100).0;
|
||||
|
||||
// States
|
||||
let hot_reload_state = Arc::new(HotReloadState {
|
||||
messages: hot_reload_tx.clone(),
|
||||
build_manager: build_manager.clone(),
|
||||
file_map: file_map.clone(),
|
||||
watcher_config: config.clone(),
|
||||
});
|
||||
@@ -175,7 +172,11 @@ pub async fn serve_hot_reload(
|
||||
&config,
|
||||
hot_reload_tx,
|
||||
file_map,
|
||||
build_manager,
|
||||
{
|
||||
let config = config.clone();
|
||||
let reload_tx = reload_tx.clone();
|
||||
move || build(&config, &reload_tx)
|
||||
},
|
||||
Some(WebServerInfo {
|
||||
ip: ip.clone(),
|
||||
port,
|
||||
@@ -473,3 +474,20 @@ async fn ws_handler(
|
||||
reload_watcher.await.unwrap();
|
||||
})
|
||||
}
|
||||
|
||||
fn build(config: &CrateConfig, reload_tx: &Sender<()>) -> Result<BuildResult> {
|
||||
let result = builder::build(&config, true)?;
|
||||
// change the websocket reload state to true;
|
||||
// the page will auto-reload.
|
||||
if config
|
||||
.dioxus_config
|
||||
.web
|
||||
.watcher
|
||||
.reload_html
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let _ = Serve::regen_dev_page(&config);
|
||||
}
|
||||
let _ = reload_tx.send(());
|
||||
Ok(result)
|
||||
}
|
||||
Reference in new issue
Block a user