Radix-Leptos SSR Bug: Client Module Unresolved

by Admin 47 views
[BUG] Issue with radix and leptos and SSR functions

Hey guys, let's dive into a tricky bug report concerning radix-leptos and its interaction with Server-Side Rendering (SSR) functions in a Leptos application. This issue surfaces when you're trying to use radix-leptos as a hydrate-only component alongside a local import. Let's break down the problem and explore potential causes.

Describe the bug

The core of the problem is that introducing radix-leptos as a hydrate-only component seems to disrupt the resolution of a local import within the Leptos application. Specifically, a module named client, which is crucial for the application's functionality, suddenly becomes unresolved when radix-leptos is added as a dependency. This is unexpected because the client module is defined with conditional compilation attributes (#[cfg(feature = "ssr")]), which should only include it during server-side rendering.

This behavior suggests a conflict or interference between radix-leptos and the conditional compilation logic. It’s like adding a new ingredient to your recipe and suddenly your oven stops working, even though the oven and the ingredient seem unrelated at first glance. We need to figure out why adding radix-leptos causes this seemingly unrelated module resolution failure. The problem arises even though radix-leptos is intended to be used primarily on the client-side during hydration. This points to a potential issue with how the features hydrate and ssr interact or how radix-leptos influences the build process.

To Reproduce

To reproduce this annoying bug, follow these steps:

  1. Set up your Leptos project: Make sure you have a working Leptos application.

  2. Add radix-leptos to your Cargo.toml: Include the following in your Cargo.toml file:

    radix-leptos = { version = "0.9.0", optional=true, features=["hydrate"] }
    
    [features]
    hydrate = ["leptos/hydrate", "dep:serde", "radix-leptos/hydrate"]
    ssr = [
    "dep:axum-extra",
      "dep:axum",
      "dep:tokio",
      "dep:tower",
      "dep:tower-http",
      "dep:leptos_axum",
      "leptos/ssr",
      "leptos_meta/ssr",
      "leptos_router/ssr",
      "dep:tracing",
      "dep:bincode",
      "dep:serde",
      "dep:interprocess",
      "dep:mime_guess",
      "dep:infer",
      "dep:tokio-util",
      "dep:rayon",
    ]
    
    [workspace.metadata.leptos]
    bin-package = "server"
    
    [profile.wasm-release]
    inherits = "release"
    opt-level = 'z'
    lto = true
    codegen-units = 1
    
    
    [package.metadata.cargo-all-features]
    denylist = ["axum", "tokio", "tower", "tower-http", "leptos_axum", "radix-leptos"]
    skip_feature_sets = [["ssr", "hydrate"], []]
    
  3. Introduce the local import: Make sure you have a local import defined with conditional compilation, similar to this:

    #[cfg(feature = "ssr")]
    #[path = "../../Rust-Hydrus/src/scr/intcoms/client.rs"]
    pub mod client;
    #[cfg(feature = "ssr")]
    #[path = "../../Rust-Hydrus/src/scr/sharedtypes.rs"]
    pub mod sharedtypes;
    
  4. Use the imported module: Attempt to use the imported module in your code:

    use client::types::ParentsType;
    
  5. Observe the error: You should now see a "use of unresolved module or unlinked crate client" error.

Expected behavior

Ideally, adding radix-leptos as a dependency should not interfere with the resolution of locally imported modules, especially when those modules are conditionally compiled using feature flags. The application should build and run without any unresolved module errors. In other words, you'd expect that introducing a UI component library wouldn't break your server-side module imports. This is crucial for maintaining a clear separation of concerns and ensuring that client-side dependencies don't inadvertently affect server-side code.

Environment

  • OS: [e.g. macOS, Windows, Linux]
  • Browser: [e.g. Chrome, Firefox, Safari]
  • Rust version: [e.g. 1.70.0]
  • Leptos version: [e.g. 0.8.0]
  • Radix-Leptos version: [e.g. 0.1.0]

It's essential to provide these details because the issue might be specific to certain environments or versions of the libraries involved. Knowing the OS, browser (if applicable), and versions of Rust, Leptos, and Radix-Leptos helps narrow down the potential causes and identify any compatibility issues.

Additional context

The quirky thing here is the way the client is imported. Let's face it; it's a bit unusual:

#[cfg(feature = "ssr")]
#[path = "../../Rust-Hydrus/src/scr/intcoms/client.rs"]
pub mod client;
#[cfg(feature = "ssr")]
#[path = "../../Rust-Hydrus/src/scr/sharedtypes.rs"]
pub mod sharedtypes;

This method relies heavily on conditional compilation based on the ssr feature flag. It's possible that radix-leptos, or its interaction with Leptos's build system, somehow alters the behavior of this conditional compilation, leading to the client module not being included when it should be. Another thing to consider is the interplay between the hydrate and ssr features. Even though radix-leptos is primarily intended for client-side hydration, its presence might influence the overall build process in a way that affects server-side code. It's also worth investigating whether the optional=true setting for radix-leptos has any unintended consequences on feature resolution.

Code Example

Here's a simple code example that uses radix-leptos:

use leptos::*;
use radix_leptos_primitives::*;

#[component]
pub fn MyComponent() -> impl IntoView {
    view! {
        <Button on_click=Callback::new(|_| println!("Clicked!"))>
            "Click me!"
        </Button>
    }
}

And here's the problematic import:

#[cfg(feature = "ssr")]
#[path = "../../Rust-Hydrus/src/scr/intcoms/client.rs"]
pub mod client;
#[cfg(feature = "ssr")]
#[path = "../../Rust-Hydrus/src/scr/sharedtypes.rs"]
pub mod sharedtypes;

The error occurs when trying to use something from the client module:

use client::types::ParentsType;

This results in the dreaded "use of unresolved module or unlinked crate client" error.

Possible Causes and Solutions

  1. Feature Flag Shenanigans: Double-check that your feature flags are correctly configured in your Cargo.toml. It's easy to make a typo or have a misunderstanding of how features interact.

  2. Build Order Issues: The order in which Cargo compiles dependencies might be a factor. Try cleaning your project (cargo clean) and rebuilding to ensure a fresh start.

  3. Conditional Compilation Quirks: The way you're using #[cfg(feature = "ssr")] might be interacting unexpectedly with radix-leptos. Experiment with different ways of conditionally including the client module.

  4. Radix-Leptos Bug: It's possible that there's a bug in radix-leptos itself that's causing this issue. Check the radix-leptos repository for similar issues or consider filing a new one.

  5. Leptos Build System: Leptos's build system might have some quirks that are contributing to the problem. Consult the Leptos documentation and community for insights.

  6. Cargo Configuration: Review your entire Cargo.toml file for any unusual settings that might be affecting dependency resolution.

  7. Check the Rust toolchain: This sounds like a crazy idea but check if your rust toolchain is updated, sometimes the rust toolchain is not compatible with the libraries.

This issue requires a bit of digging to fully understand. By systematically investigating the potential causes and experimenting with different solutions, you should be able to track down the root of the problem and get your Leptos application working smoothly with radix-leptos.