1

TLDR

Total n00b with rust, yew and trunk.

I want to find out how to rust, yew and trunk to build an HTML file containing just one DOM node, not a whole HTML page.

Background

Day-to-day, I use Django, the python web framework. Its admin console uses HTML template rendering, and an example of a template might look like this:

{% extends 'django_twined/question_changeform.html' %}

{% block object-tools-items %}
    {% if show_set_active %}
        <li><a href="?set_active=True">Set active</a></li>
    {% endif %}
    {{ block.super }}
{% endblock %}

Where in this example the {% %} and {{ }} get evaluated at render time into a valid HTML structure (from other template files), and the <li> is an extra node that gets added to the DOM.

Instead of a vanilla li element, I want to build a complex DOM node using Rust/Yew/Trunk. Then I can include the resulting head and body elements file in a django template, something like:

{% extends 'django_twined/question_changeform.html' %}

{% block head %}
    {{ block.super }}
    <!-- Include the scripts generated by trunk build -->
    {% include 'my-dom-node-head.html' %}
{% endblock %}

{% block object-tools-items %}
    <!-- Include the elements generated by trunk build -->
    {% include 'my-dom-node-body.html' %}
    {{ block.super }}
{% endblock %}

Where I'm at

I've used the yew starter app to get myself to an app. The input index.html is:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Yew App</title>
  </head>
</html>

And the main.rs file looks like:

use yew::prelude::*;

enum Msg {
    AddOne,
}

struct Model {
    value: i64,
}

impl Component for Model {
    type Message = Msg;
    type Properties = ();

    fn create(_ctx: &Context<Self>) -> Self {
        Self {
            value: 0,
        }
    }

    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            Msg::AddOne => {
                self.value += 1;
                // the value has changed so we need to
                // re-render for it to appear on the page
                true
            }
        }
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        // This gives us a component's "`Scope`" which allows us to send messages, etc to the component.
        let link = ctx.link();
        html! {
            <div>
                <button onclick={link.callback(|_| Msg::AddOne)}>{ "+1" }</button>
                <p>{ self.value }</p>
            </div>
        }
    }
}

fn main() {
    yew::start_app::<Model>();
}

After trunk build, the output index.html looks like:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Yew App</title>
    <link
      rel="preload"
      href="/yew-app-caccf6c60742c530_bg.wasm"
      as="fetch"
      type="application/wasm"
      crossorigin=""
    />
    <link rel="modulepreload" href="/yew-app-caccf6c60742c530.js" />
  </head>

  <body>
    <script type="module">
      import init from "/yew-app-caccf6c60742c530.js";
      init("/yew-app-caccf6c60742c530_bg.wasm");
    </script>
  </body>
</html>

Where next?

So basically I need to get the <link> and <script> elements added by trunk build and put them into my template.

What should I do next? Would you suggest I try to:

  • Get trunk build --filehash false to output deterministic .js and .wasm file names without the hash (caccf6c60742c530 in this case) so that I can directly write the includes into my template (I'm concerned this will cause me development problems down the road)?
  • Get trunk build to output separate head link and body script?
  • Post-process the output index.html to extract the inserted scripts?
  • Alter main.rs in some way to output only what I need/want?
thclark
  • 4,784
  • 3
  • 39
  • 65
  • I'm not quite sure if this is what you want, but here is a rust crate [tera](https://tera.netlify.app/) that could help you. It's a templating engine very similar to one used by django. – Aleksander Krauze Oct 16 '22 at 12:42
  • 1
    @AleksanderKrauze that might be extremely useful to me in future, thank you - although agree that it might not be quite a fit here. – thclark Oct 16 '22 at 12:45
  • What would be extremely cool is if there were some kind of tera-yew plugin that allowed you to generate templates for yew then render them with tera. It'd work exactly like React where you can just add react to whatever node in the HTML you want. – thclark Oct 16 '22 at 12:48

0 Answers0