dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

Special elements `head` and `body`

Open itsezc opened this issue 2 years ago • 8 comments

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

itsezc avatar Jul 09 '23 01:07 itsezc

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 avatar Jul 10 '23 16:07 ealmloff

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?

JeanMertz avatar Jul 28 '23 03:07 JeanMertz

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)

ealmloff avatar Jul 28 '23 03:07 ealmloff

@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.

itsezc avatar Dec 28 '23 17:12 itsezc

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

ealmloff avatar Jan 10 '24 22:01 ealmloff

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.

ochrons avatar Mar 09 '24 13:03 ochrons

@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:

  • https://fr.example.com/
  • https://example.fr/ (if available)
  • https://example.com/fr

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

tkr-sh avatar Mar 31 '24 11:03 tkr-sh

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.

jkelleyrtp avatar Apr 26 '24 16:04 jkelleyrtp