Watch A Directory For File Changes While Hot Reloading Web Pages
This is the process I'm using for Neopoligin to rebuild and reload the site when source files change.
Code
use axum::Router;
use notify::RecursiveMode;
use notify::Watcher;
use notify_debouncer_mini::new_debouncer;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::time::Duration;
use tower_http::services::ServeDir;
use tower_livereload::LiveReloadLayer;
#[tokio::main]
async fn main() {
tokio::spawn(async {
let _ = watch_files();
});
let _ = run_web_server().await;
}
async fn run_web_server() -> std::result::Result<(), Box<dyn std::error::Error>> {
let livereload = LiveReloadLayer::new();
let reloader = livereload.reloader();
let app = Router::new()
.nest_service("/", ServeDir::new(Path::new("html")))
.layer(livereload);
let mut watcher = notify::recommended_watcher(move |_| reloader.reload())?;
watcher.watch(Path::new("html"), notify::RecursiveMode::Recursive)?;
axum::Server::bind(&"0.0.0.0:3030".parse()?)
.serve(app.into_make_service())
.await?;
Ok(())
}
fn watch_files() -> notify::Result<()> {
let watch_dir = PathBuf::from("/some/source/dir");
let output_file =
PathBuf::from("/some/output/file.html");
let (tx, rx) = std::sync::mpsc::channel();
let mut debouncer = new_debouncer(Duration::from_millis(100), tx)?;
debouncer
.watcher()
.watch(&watch_dir, RecursiveMode::Recursive)?;
for result in rx {
match result {
Ok(events) => events.iter().for_each(|event| {
// BUILD FROM SOURCE FILE HERE
let _ = fs::write(
output_file.clone(),
format!("{}", &event.path.display())
);
}),
Err(_) => {}
}
}
Ok(())
}
Installs
Code
cargo add axum
cargo add tokio --features "rt-multi-thread,macros"
cargo add tower-http --features "fs"
cargo add tower-livereload
cargo add notify
cargo add notify_debouncer_mini