Note: This site is currently "Under construction". I'm migrating to a new version of my site building software. Lots of things are in a state of disrepair as a result (for example, footnote links aren't working). It's all part of the process of building in public. Most things should still be readable though.

Watch A Content Directory And Do A Live Reload Of Pages In An Axum Web Server Embedded In Tauri When They Change

Code

Cargo.toml
[package]
name = "tauri_neopoligen_prototype"
version = "0.0.1"
description = "Tauri With Axum Embedded"
license = ""
repository = ""
edition = "2021"

[build-dependencies]
tauri-build = { version = "1.5", features = [] }

[dependencies]
tauri = { version = "1.5", features = ["shell-open"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
axum = "0.7.4"
tower-http = { version = "0.5.1", features = ["fs"] }
tower-livereload = "0.9.1"
tokio = { version = "1.35.1"}
# tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] }
notify = "6.1.1"
notify-debouncer-mini = "0.4.1"

[features]
# this feature is used for production builds or when `devPath` points to the filesystem
# DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"]

Code

// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use axum::Router;
use notify_debouncer_mini::{new_debouncer, notify::*, DebounceEventResult};
use std::path::Path;
use std::time::Duration;
use tower_http::services::ServeDir;
use tower_livereload::LiveReloadLayer;

fn main() {
    tauri::Builder::default()
        .setup(|_app| {
            tauri::async_runtime::spawn(run_web_server());
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

async fn run_web_server() {
    println!("- Starting web server");
    let livereload = LiveReloadLayer::new();
    let reloader = livereload.reloader();
    let app = Router::new()
        .nest_service(
            "/",
            ServeDir::new(Path::new("/Users/alan/workshop/neopoligen/_site")),
        )
        .layer(livereload);
    let mut debouncer = new_debouncer(
        Duration::from_millis(150),
        move |res: DebounceEventResult| match res {
            Ok(events) => events.iter().for_each(|e| {
                println!("Event {:?} for {:?}", e.kind, e.path);
                reloader.reload();
                ()
            }),
            Err(e) => println!("Error {:?}", e),
        },
    )
    .unwrap();
    debouncer
        .watcher()
        .watch(
            Path::new("/Users/alan/workshop/neopoligen/_content"),
            RecursiveMode::Recursive,
        )
        .unwrap();
    if let Ok(listener) = tokio::net::TcpListener::bind("localhost:8338").await {
        if let Ok(_) = axum::serve(listener, app).await {
            ()
        } else {
            ()
        }
    } else {
        ()
    }
    ()
}