Use ServeDir for fullstack dev static assets
Without this patch, simply instantiating the Jumpstart template in fullstack mode and making any hot-patch change results in a 404 on fetch and a client WASM panic.
This changes the fullstack server static asset routing so that, in debug builds, directories under the public tree (including /wasm) are served via tower_http::services::ServeDir instead of being eagerly expanded into a fixed set of routes at startup.
Today dioxus_server::DioxusRouterExt::serve_static_assets walks the public directory once at launch via serve_dir_cached, registering a separate route for every file it sees. That works fine for pre-baked assets, but it breaks down when dx/subsecond writes new files into public during a dev session. In a fullstack web app, wasm hot patches are emitted as timestamped files like public/wasm/lib<name>-patch-<ts>.wasm; the CLI tells the browser to fetch /wasm/lib<name>-patch-<ts>.wasm immediately, but the fullstack server never registered a route for that path, so the fetch returns 404 even though the file already exists on disk.
Non-fullstack dev builds do not have this problem because the dx devserver serves public directly using ServeDir, which consults the filesystem at request time. Fullstack dev, by contrast, proxies asset requests to the inner server, and that server only knows about whatever was in public at the moment its router was built.
This change narrows the gap by making serve_static_assets dynamic for directories in debug builds while preserving the existing behaviour elsewhere:
- For debug builds (
cfg(debug_assertions)),serve_dir_cachednow usesServeDir::new(&path)when it encounters a directory. This means/wasm,/assets, and any other subdirectories are backed by a live directory listing, so new files like wasm patch modules and freshly emitted hashed CSS become immediately visible without restarting the fullstack server or rebuilding its router. - For non-debug builds, the previous behaviour is preserved:
serve_dir_cachedcontinues to recurse and register one route per discovered file, still usingServeFile::precompressed_br()andcache_response_foreverfor hashed, cache-busted filenames.
This is a no-op for release builds, but in debug fullstack it's necessary for wasm hot patches and other dynamically-created assets that could 404 until the server happened to be restarted. It also aligns fullstack dev behaviour more closely with the plain web devserver, which already uses ServeDir for the public tree.
As a total aside – fullstack is slick! Thanks so much for setting this up, it feels great to use!
Important note about this PR: to be useful, it'd be reliant on teaching the reloader to do a full rebuild, not a hot patching one. This works great in non-hot-patch scenarios, but the code as a whole around this needs more work to ensure it forces a full rebuild in hot patch situations.