Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Public leptos_meta::register function #3230

Open
luoxiaozero opened this issue Nov 11, 2024 · 3 comments
Open

Public leptos_meta::register function #3230

luoxiaozero opened this issue Nov 11, 2024 · 3 comments

Comments

@luoxiaozero
Copy link
Contributor

Is your feature request related to a problem? Please describe.

Currently I inject css into head via Style in SSR mode, and control css via custom logic in Hydrate mode.

fn mount_style(id: &str, content: &'static str) {
    if #[cfg(feature = "ssr")] {
        let _ = view! {
            <Style id=id>
                {content}
            </Style>
        };
    } else {
        let head = document().head().expect("head no exist");
        let style = head
            .query_selector(&format!("style#{id}"))
            .expect("query style element error");
        if style.is_some() {
            return;
        }
        let style = document()
            .create_element("style")
            .expect("create style element error");
        _ = style.set_attribute("id", &id);
        style.set_text_content(Some(content));
        _ = head.prepend_with_node_1(&style);
    }
}

When I hydrate via the following code, <Style>". b {}"</Style> gets hydrated to the <style>". a{}"</style> element instead of the <style>". b{}"</style> element.

#[component]
pub fn Button() -> impl IntoView {
    mount_style("button", ".a {}");
    view! {
        <Style>
             ".b {}"
         </Style>
    }
}

Describe the solution you'd like

Public leptos_meta::register function. Allows passing a second parameter to control the position of the generated HTML string to avoid hydration.

pub fn register<E, At, Ch>(
    el: HtmlElement<E, At, Ch>,
    config: RegisterConfig,
) -> RegisteredMetaTag<E, At, Ch>

pub struct RegisterConfig {
    position: ElementPosition
}

pub enum ElementPosition {
    // Before the <!--HEAD--> comment.
    MarkerBefore,
    // After the <!--HEAD--> comment.
    MarkerAfter,
}

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context

RegisterConfig is a struct in order to expand more fields in the future to achieve the same functions as unhead.

@gbj
Copy link
Collaborator

gbj commented Nov 11, 2024

It seems like there are multiple people interested in having the ability to inject things into the <head> where leptos_meta does it, while also modifying the behavior of the relevant components pretty signficantly. (See #2856, #3188) It would be helpful to unite these different ideas into one set of extensions to leptos_meta.

I think at least #2856 and this seem to result from the fact that the pre-0.7 leptos_meta components have side effects — simply creating a <Style>, without every using it in the view that is returned, injects something into the <head>. It seems like your implementation above relies on this behavior. (i.e., mount_style does not return a view that should be rendered, but () — it is purely side effects)

I don't think I fully understand either the use case for what you're trying to do, or what you're asking for, though.

@luoxiaozero
Copy link
Contributor Author

luoxiaozero commented Dec 12, 2024

I found a way to solve this problem without modifying leptos. Refer to the SSRMountStyleProvider component in thaw-ui/thaw@266dd6d.

In addition, I think the core problem is that the functions of leptos_meta are not perfect enough. Unlike nextjs's Head and nuxtjs's unhead, there are key value deduplication, injected tag reordering, etc. And recently I wanted to implement the above functions for leptos_meta, but found that it can only be refactored on a large scale.

solid-meta has always had related issues, but they have never been resolved.

@gbj
Copy link
Collaborator

gbj commented Dec 12, 2024

I think the core problem is that the functions of leptos_meta are not perfect enough... And recently I wanted to implement the above functions for leptos_meta, but found that it can only be refactored on a large scale.

To be honest, I'm not sure what to do with feedback like this.

As far as I can tell there are no open issues reporting bugs in leptos_meta. The only open issues I know of are people asking to change parts of the API. That makes it difficult to know whether that is a good idea, as people are either not running into issues with the current API or not raising them with me.

Perhaps there is another set of APIs that need to be exposed, which would be imperative/procedure-based, rather than declarative/component-based APIs. This relates to both your example and to #2856. I am open to doing that, if you have ideas on useful ways to do it. I am probably not the right person to design or implement those ideas, as I do not have any experience with the libraries you're citing as good examples.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants