create websocket for hot reloading
This commit is contained in:
1 parent
07199c8a64
commit
e7cf382784
2 files changed
+69
No files matched your search
@@ -16,6 +16,7 @@ dioxus-html = { path = "../html", version = "^0.2.1", features = ["wasm-bind"] }
|
|||||||
dioxus-interpreter-js = { path = "../interpreter", version = "^0.2.1", features = [
|
dioxus-interpreter-js = { path = "../interpreter", version = "^0.2.1", features = [
|
||||||
"web"
|
"web"
|
||||||
] }
|
] }
|
||||||
|
dioxus-rsx-interpreter = { path = "../rsx_interpreter", version = "*", optional = true }
|
||||||
|
|
||||||
js-sys = "0.3.56"
|
js-sys = "0.3.56"
|
||||||
wasm-bindgen = { version = "0.2.79", features = ["enable-interning"] }
|
wasm-bindgen = { version = "0.2.79", features = ["enable-interning"] }
|
||||||
@@ -30,6 +31,7 @@ futures-util = "0.3.19"
|
|||||||
smallstr = "0.2.0"
|
smallstr = "0.2.0"
|
||||||
serde-wasm-bindgen = "0.4.2"
|
serde-wasm-bindgen = "0.4.2"
|
||||||
futures-channel = "0.3.21"
|
futures-channel = "0.3.21"
|
||||||
|
serde_json = { version = "1.0", optional = true }
|
||||||
|
|
||||||
[dependencies.web-sys]
|
[dependencies.web-sys]
|
||||||
version = "0.3.56"
|
version = "0.3.56"
|
||||||
@@ -75,6 +77,7 @@ features = [
|
|||||||
[features]
|
[features]
|
||||||
default = ["panic_hook"]
|
default = ["panic_hook"]
|
||||||
panic_hook = ["console_error_panic_hook"]
|
panic_hook = ["console_error_panic_hook"]
|
||||||
|
hot_reload = ["dioxus-rsx-interpreter", "web-sys/WebSocket", "web-sys/Location", "web-sys/MessageEvent", "serde_json"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dioxus-core-macro = { path = "../core-macro" }
|
dioxus-core-macro = { path = "../core-macro" }
|
||||||
|
|||||||
@@ -217,6 +217,72 @@ pub async fn run_with_props<T: 'static + Send>(root: Component<T>, root_props: T
|
|||||||
|
|
||||||
let mut work_loop = ric_raf::RafLoop::new();
|
let mut work_loop = ric_raf::RafLoop::new();
|
||||||
|
|
||||||
|
#[cfg(feature = "hot_reload")]
|
||||||
|
{
|
||||||
|
use dioxus_rsx_interpreter::error::Error;
|
||||||
|
use dioxus_rsx_interpreter::{ErrorHandler, SetRsxMessage, RSX_CONTEXT};
|
||||||
|
use futures_channel::mpsc::unbounded;
|
||||||
|
use futures_channel::mpsc::UnboundedSender;
|
||||||
|
use futures_util::StreamExt;
|
||||||
|
use wasm_bindgen::closure::Closure;
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
|
use web_sys::{MessageEvent, WebSocket};
|
||||||
|
|
||||||
|
let window = web_sys::window().unwrap();
|
||||||
|
|
||||||
|
let protocol = if window.location().protocol().unwrap() == "https:" {
|
||||||
|
"wss:"
|
||||||
|
} else {
|
||||||
|
"ws:"
|
||||||
|
};
|
||||||
|
|
||||||
|
let url = format!(
|
||||||
|
"{protocol} //{}/_dioxus/hot_reload",
|
||||||
|
window.location().host().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let ws = WebSocket::new(&url).unwrap();
|
||||||
|
|
||||||
|
// change the rsx when new data is received
|
||||||
|
let cl = Closure::wrap(Box::new(|e: MessageEvent| {
|
||||||
|
if let Ok(text) = e.data().dyn_into::<js_sys::JsString>() {
|
||||||
|
let msg: SetRsxMessage = serde_json::from_str(&format!("{text}")).unwrap();
|
||||||
|
RSX_CONTEXT.insert(msg.location, msg.new_text);
|
||||||
|
}
|
||||||
|
}) as Box<dyn FnMut(MessageEvent)>);
|
||||||
|
|
||||||
|
ws.set_onmessage(Some(cl.as_ref().unchecked_ref()));
|
||||||
|
|
||||||
|
let (error_channel_sender, error_channel_receiver) = unbounded();
|
||||||
|
|
||||||
|
struct WebErrorHandler {
|
||||||
|
sender: UnboundedSender<Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ErrorHandler for WebErrorHandler {
|
||||||
|
fn handle_error(&self, err: dioxus_rsx_interpreter::error::Error) {
|
||||||
|
self.sender.unbounded_send(err).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RSX_CONTEXT.set_error_handler(WebErrorHandler {
|
||||||
|
sender: error_channel_sender,
|
||||||
|
});
|
||||||
|
|
||||||
|
// forward stream to the websocket
|
||||||
|
dom.base_scope().spawn_forever(async move {
|
||||||
|
error_channel_receiver
|
||||||
|
.for_each(|err| {
|
||||||
|
if let Error::RecompileRequiredError(err) = err {
|
||||||
|
ws.send_with_str(serde_json::to_string(&err).unwrap().as_str())
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
futures_util::future::ready(())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
log::trace!("waiting for work");
|
log::trace!("waiting for work");
|
||||||
// if virtualdom has nothing, wait for it to have something before requesting idle time
|
// if virtualdom has nothing, wait for it to have something before requesting idle time
|
||||||
|
|||||||
Reference in new issue
Block a user