dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

With SSG, fallback / 404 route does not seem to work?

Open rogusdev opened this issue 1 year ago • 2 comments

Problem

Using SSG, it seems that a NotFound route ala https://dioxuslabs.com/learn/0.6/router/example/first-route#fallback-route does not actually get matched, instead just the Home route gets displayed.

Is this a bug, or am I perhaps misunderstanding something important that I would need to do for SSG with nonexistent routes?

I have a suspicion that perhaps this bug is also related to seeing the home/root/index route flash up before showing a proper route ala: https://github.com/DioxusLabs/dioxus/issues/3641

Steps To Reproduce

use dioxus::prelude::*;

#[component]
fn App() -> Element {
    rsx! {
        Router::<Route> {}
    }
}

#[component]
fn Home() -> Element {
    rsx! {
        h1 { "Home" }
    }
}

#[component]
fn Other() -> Element {
    rsx! {
        h1 { "Other" }
    }
}

#[component]
pub fn NotFound(route: Vec<String>) -> Element {
    let route_str = route.join("/");

    rsx! {
        h1 {
            "404 - {route_str}"
        }
    }
}

#[derive(Routable, Clone, PartialEq)]
pub enum Route {
    #[route("/")]
    Home {},
    #[route("/other")]
    Other {},
    #[route("/:..route")]
    NotFound { route: Vec<String> },
}

fn main() {
    dioxus::LaunchBuilder::new()
        // Set the server config only if we are building the server target
        .with_cfg(server_only! {
            ServeConfig::builder()
                // Enable incremental rendering
                .incremental(
                    IncrementalRendererConfig::new()
                        // Store static files in the public directory where other static assets like wasm are stored
                        .static_dir(
                            std::env::current_exe()
                                .unwrap()
                                .parent()
                                .unwrap()
                                .join("public")
                        )
                        // Don't clear the public folder on every build. The public folder has other files including the wasm
                        // binary and static assets required for the app to run
                        .clear_cache(false)
                )
                .enable_out_of_order_streaming()
        })
        .launch(App);
}

// The server function at the endpoint "static_routes" will be called by the CLI to generate the list of static
// routes. You must explicitly set the endpoint to `"static_routes"` in the server function attribute instead of
// the default randomly generated endpoint.
#[server(endpoint = "static_routes")]
async fn static_routes() -> Result<Vec<String>, ServerFnError> {
    // The `Routable` trait has a `static_routes` method that returns all static routes in the enum
    Ok(Route::static_routes().iter().map(ToString::to_string).collect())
}

Run it with:

rm -rf target && dx serve --platform web --ssg --release
  • http://127.0.0.1:8080/ shows Home
  • http://127.0.0.1:8080/other shows Other
  • http://127.0.0.1:8080/dne shows Home when it should show 404 - dne (which it does without SSG)

Expected behavior

NotFound / fallback routes should work even with SSG

Environment:

dioxus = { version = "0.6.2", features = ["router", "fullstack"] }

rogusdev avatar Jan 24 '25 19:01 rogusdev

More discussion here: https://discord.com/channels/899851952891002890/1276184595192348764/1332433392599302195

rogusdev avatar Jan 24 '25 19:01 rogusdev

I think this is a hydration issue. When the server renders the /index.html route during SSG, it renders the homepage. When the client hydrates the /dne url it tries to hydrate the fallback route but fails because the HTML is for the /index.html route

ealmloff avatar Jan 24 '25 20:01 ealmloff