hot_reload.rs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. use std::sync::{Arc, Mutex};
  2. use axum::{
  3. extract::{ws::Message, WebSocketUpgrade},
  4. response::IntoResponse,
  5. Extension, TypedHeader,
  6. };
  7. use dioxus_core::Template;
  8. use dioxus_html::HtmlCtx;
  9. use dioxus_rsx::hot_reload::FileMap;
  10. use tokio::sync::broadcast;
  11. use super::BuildManager;
  12. use crate::CrateConfig;
  13. pub struct HotReloadState {
  14. pub messages: broadcast::Sender<Template<'static>>,
  15. pub build_manager: Arc<BuildManager>,
  16. pub file_map: Arc<Mutex<FileMap<HtmlCtx>>>,
  17. pub watcher_config: CrateConfig,
  18. }
  19. pub async fn hot_reload_handler(
  20. ws: WebSocketUpgrade,
  21. _: Option<TypedHeader<headers::UserAgent>>,
  22. Extension(state): Extension<Arc<HotReloadState>>,
  23. ) -> impl IntoResponse {
  24. ws.on_upgrade(|mut socket| async move {
  25. log::info!("🔥 Hot Reload WebSocket connected");
  26. {
  27. // update any rsx calls that changed before the websocket connected.
  28. {
  29. log::info!("🔮 Finding updates since last compile...");
  30. let templates: Vec<_> = {
  31. state
  32. .file_map
  33. .lock()
  34. .unwrap()
  35. .map
  36. .values()
  37. .filter_map(|(_, template_slot)| *template_slot)
  38. .collect()
  39. };
  40. for template in templates {
  41. if socket
  42. .send(Message::Text(serde_json::to_string(&template).unwrap()))
  43. .await
  44. .is_err()
  45. {
  46. return;
  47. }
  48. }
  49. }
  50. log::info!("finished");
  51. }
  52. let mut rx = state.messages.subscribe();
  53. loop {
  54. if let Ok(rsx) = rx.recv().await {
  55. if socket
  56. .send(Message::Text(serde_json::to_string(&rsx).unwrap()))
  57. .await
  58. .is_err()
  59. {
  60. break;
  61. };
  62. }
  63. }
  64. })
  65. }