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

Special elements head and body #1169

Closed
itsezc opened this issue Jul 9, 2023 · 8 comments · Fixed by #2635
Closed

Special elements head and body #1169

itsezc opened this issue Jul 9, 2023 · 8 comments · Fixed by #2635
Labels
enhancement New feature or request html Related to the html crate
Milestone

Comments

@itsezc
Copy link

itsezc commented Jul 9, 2023

Specific Demand

Borrowing an idea from Svelte here, but it'd be great if this is built into Dioxus, very useful when developing for the Web and PWAs.

Implement Suggestion

Current implementation of dioxus-helmet looks good, it'd be great if we can bring this in house and offer it out of the box

@ealmloff
Copy link
Member

head and body elements are difficult because they need to already exist for the application to load.

The approach dioxus-helmet takes will only work for web renderers because it depends on web-sys.

The head must include a link to the .js and .wasm files that start Dioxus. It is unclear how to handle updating the existing head and body elements when rendering a page.

For example, a demo application today needs to include something like this to start the application:

<head>
  <title>Floneum</title>
  <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta charset="UTF-8">
  <link rel="preload" href="/floneum-site_bg.wasm" as="fetch" type="application/wasm" 
  crossorigin="">
  <link rel="modulepreload" href="/floneum-site.js"></head>
</head>

We would either need to force users to include that boilerplate in every application or ignore that part of the head when diffing (which would make changing something like the title difficult).

head {
  title {
      "Floneum"
  }
  meta { content: "text/html;charset=utf-8", http_equiv: "Content-Type" }
  meta { name: "viewport", content: "width=device-width, initial-scale=1" }
  meta { charset: "UTF-8" }
  link { rel: "preload", href: "/floneum-site_bg.wasm", as: "fetch", type: "application/wasm", 
  crossorigin: "" }
  link { rel: "modulepreload", href: "/floneum-site.js" }
}

Or a third option is auto-inserting the scripts if no head and body element are found, otherwise generating the links to the scripts

@ealmloff ealmloff added enhancement New feature or request html Related to the html crate labels Jul 10, 2023
@JeanMertz
Copy link

I second this request. However, dioxus-helmet isn't enough in my case, as I need to actually add properties to both the html and body elements.

I don't mind so much whether I can access these elements programmatically, as long as I can define the properties to be there when the page is compiled.

Leptos has a mount_to_body function, which binds the app to an existing body element in an existing index.html file. That would be ideal in my case.

For now, I'm going to see if I can work around this by having a build step that manipulates dist/index.html after it's generated. Not ideal, but I don't believe there is any other way currently with Dioxus?

@ealmloff
Copy link
Member

ealmloff commented Jul 28, 2023

I second this request. However, dioxus-helmet isn't enough in my case, as I need to actually add properties to both the html and body elements.

I don't mind so much whether I can access these elements programmatically, as long as I can define the properties to be there when the page is compiled.

Leptos has a mount_to_body function, which binds the app to an existing body element in an existing index.html file. That would be ideal in my case.

For now, I'm going to see if I can work around this by having a build step that manipulates dist/index.html after it's generated. Not ideal, but I don't believe there is any other way currently with Dioxus?

mount_to_body and the dioxus_web::launch macro work similarly. Both will insert the WASM application in some existing HTML. Dioxus will just create a default html file if you don't provide one

If you create a index.html file in the same directory as your cargo.toml, the Dioxus CLI will use that html file to build the final html file. In the 0.3 release, your index.html file needs to fix this template. (The git version of the CLI relaxes this a bit)

@itsezc
Copy link
Author

itsezc commented Dec 28, 2023

@ealmloff I hope with 0.6.0 of integrating helmet, we can set more than just the title, but anything arbitrary in the head or body i.e. meta tags, loading scripts / stylesheets etc.

@ealmloff
Copy link
Member

It might make more sense to create a cross platform head hook that lets you change things like the title. That would also make it easier to add any desktop specific extensions to the same hook

Some other parts of this we want to do at compile time with a macro if possible:
For dioxus web (without fullstack) you want to be able to set things like meta tags at compile time
For dioxus desktop, you want to collect assets for bundling

@ochrons
Copy link

ochrons commented Mar 9, 2024

It's absolutely necessary to be able to include route specific content in the head. This is important for being able to present meta data for content preview and SEO purposes. Also proper multilingual support would need to set the lang attribute on HTML based on the selected language (coming from the route).

This cannot be done "post load" in JavaScript but needs to happen on the server side when rendering the HTML page.

For example https://example.com/my-blog-post?lang=fr should result into something like

<html lang="fr">
<head>
  <meta charset="UTF-8">
  <meta property="og:locale" content="en_US">
  <meta property="og:title" content="Mon article de blog">
  <meta property="og:url" content="https://example.com/my-blog-post?lang=fr">
  <meta property="og:description" content="Un excellent article de blog sur Dioxus">
  <title>Mon article de blog</title>
  ... other relevant tags ...
</head>

If it wasn't for the routes, this could be done outside of Dioxus, like on axum level, but with routes containing relevant information for the head, there needs to be proper support for this inside Dioxus.

Furthermore, as some content for the head tags would be coming from external sources, like a database, there needs to be a way to update these tags within the rendering functions waiting for use_server_future etc.

Perhaps having a template for the head with specific placeholders for meta data would be a good and safe approach to do this. Then exposing those template locations within the global context or so.

@tkr-sh
Copy link
Contributor

tkr-sh commented Mar 31, 2024

@ochrons I understand what you say, and I think the same thing.
But in your particular example, using ?lang=fr is terrible for SEO.
If you want a better SEO use either:

More info here: https://webmasters.stackexchange.com/questions/403/how-should-i-structure-my-urls-for-both-seo-and-localization

@jkelleyrtp
Copy link
Member

We might just end up going the react 19 route

https://react.dev/blog/2024/04/25/react-19#support-for-metadata-tags

This would be even easier than looking for a head element.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request html Related to the html crate
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

6 participants