implement hot reloading for liveview

This commit is contained in:
Evan Almloff committed 2023-01-11 14:41:29 -06:00
1 parent 6eff4438cf
commit e5e1abbdac
4 files changed
+58 -4

No files matched your search

+7 -4
View File
@@ -13,6 +13,10 @@ license = "MIT/Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus-html = { path = "../html", features = ["serialize"], version = "^0.3.0" }
dioxus-core = { path = "../core", features = ["serialize"], version = "^0.3.0" }
dioxus-interpreter-js = { path = "../interpreter", version = "0.3.0" }
tokio = { version = "1.23.0", features = ["full"] }
futures-util = { version = "0.3.25", default-features = false, features = [
"sink",
@@ -25,9 +29,7 @@ serde = { version = "1.0.151", features = ["derive"] }
serde_json = "1.0.91"
tokio-util = { version = "0.7.4", features = ["full"] }
dioxus-html = { path = "../html", features = ["serialize"], version = "^0.3.0" }
dioxus-core = { path = "../core", features = ["serialize"], version = "^0.3.0" }
dioxus-interpreter-js = { path = "../interpreter", version = "0.3.0" }
interprocess = { version = "1.2.1", optional = true }
# warp
warp = { version = "0.3.3", optional = true }
@@ -56,8 +58,9 @@ salvo = { version = "0.37.7", features = ["affix", "ws"] }
tower = "0.4.13"
[features]
default = []
default = ["hot-reload"]
# actix = ["actix-files", "actix-web", "actix-ws"]
hot-reload = ["interprocess"]
[[example]]
name = "axum"
+31
View File
@@ -0,0 +1,31 @@
#![allow(dead_code)]
use dioxus_core::Template;
use interprocess::local_socket::LocalSocketStream;
use std::io::{BufRead, BufReader};
use tokio::sync::mpsc::UnboundedSender;
pub(crate) fn init(proxy: UnboundedSender<Template<'static>>) {
std::thread::spawn(move || {
let temp_file = std::env::temp_dir().join("@dioxusin");
if let Ok(socket) = LocalSocketStream::connect(temp_file.as_path()) {
let mut buf_reader = BufReader::new(socket);
loop {
let mut buf = String::new();
match buf_reader.read_line(&mut buf) {
Ok(_) => {
let template: Template<'static> =
serde_json::from_str(Box::leak(buf.into_boxed_str())).unwrap();
proxy.send(template).unwrap();
}
Err(err) => {
if err.kind() != std::io::ErrorKind::WouldBlock {
break;
}
}
}
}
}
});
}
+2
View File
@@ -18,6 +18,8 @@ pub mod adapters {
pub use adapters::*;
#[cfg(all(feature = "hot-reload", debug_assertions))]
mod hot_reload;
pub mod pool;
use futures_util::{SinkExt, StreamExt};
pub use pool::*;
+18
View File
@@ -103,6 +103,13 @@ pub async fn run<T>(
where
T: Send + 'static,
{
#[cfg(all(feature = "hot-reload", debug_assertions))]
let mut hot_reload_rx = {
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
crate::hot_reload::init(tx);
rx
};
let mut vdom = VirtualDom::new_with_props(app, props);
// todo: use an efficient binary packed format for this
@@ -122,6 +129,11 @@ where
}
loop {
#[cfg(all(feature = "hot-reload", debug_assertions))]
let hot_reload_wait = hot_reload_rx.recv();
#[cfg(not(all(feature = "hot-reload", debug_assertions)))]
let hot_reload_wait = std::future::pending();
tokio::select! {
// poll any futures or suspense
_ = vdom.wait_for_work() => {}
@@ -138,6 +150,12 @@ where
None => return Ok(()),
}
}
new_template = hot_reload_wait => {
if let Some(new_template) = new_template {
vdom.replace_template(new_template);
}
}
}
let edits = vdom