Creating extremely efficient templates

We have seen that Rust is a really efficient language and as you have seen in the last two chapters, metaprogramming allows for the creation of even more efficient code. Rust has great templating language support, such as Handlebars and Tera. Rust's Handlebars implementation is much faster than the JavaScript implementation, while Tera is a template engine created for Rust based on Jinja2.

In both cases, you define a template file and then you use Rust to parse it. Even though this will be reasonable for most web development, in some cases, it might be slower than pure Rust alternatives. This is where the Maud crate comes in. We will see how it works and how it achieves orders of magnitude faster performance than its counterparts.

To use Maud, you will need nightly Rust, since it uses procedural macros. As we saw in previous chapters, if you are using rustup you can simply run rustup override set nightly. Then, you will need to add Maud to your Cargo.toml file in the [dependencies] section:

[dependencies]
maud = "0.17.2

Maud brings an html!{} procedural macro that enables you to write HTML in Rust. You will therefore need to import the necessary crate and macro in your main.rs or lib.rs file, as you will see in the following code. Remember to also add the procedural macro feature at the beginning of the crate:

#![feature(proc_macro)]

extern crate maud;
use maud::html;

You will now be able to use the html!{} macro in your main() function. This macro will return a Markup object, which you can then convert to a String or return to Rocket or Iron for your website implementation (you will need to use the relevant Maud features in that case). Let's see what a short template implementation looks like:

fn main() {
use maud::PreEscaped;

let user_name = "FooBar";
let markup = html! {
(PreEscaped("<!DOCTYPE html>"))
html {
head {
title { "Test website" }
meta charset="UTF-8";
}
body {
header {
nav {
ul {
li { "Home" }
li { "Contact Us" }
}
}
}
main {
h1 { "Welcome to our test template!" }
p { "Hello, " (user_name) "!" }
}
footer {
p { "Copyright © 2017 - someone" }
}
}
}
};
println!("{}", markup.into_string());
}

It seems like a complex template, but it contains just the basic information a new website should have. We first add a doctype, making sure it will not escape the content (that is what the PreEscaped is for) and then we start the HTML document with two parts: the head and the body. In the head, we add the required title and the charset meta element to tell the browser that we will be using UTF-8.

Then, the body contains the three usual sections, even though this can of course be modified. One header, one main section, and one footer. I added some example information in each of the sections and showed you how to add a dynamic variable in the main section inside a paragraph.

The interesting syntax here is that you can create elements with attributes, such as the meta element, even without content, by finishing it early with a semicolon. You can use any HTML tag and add variables. The generated code will be escaped, except if you ask for non-escaped data, and it will be minified so that it occupies the least space when being transmitted.

Inside the parentheses, you can call any function or variable that returns a type that implements the Display trait and you can even add any Rust code if you add braces around it, with the last statement returning a Display element. This works on attributes too.

This gets processed at compile time, so that at runtime it will only need to perform the minimum possible amount of work, making it extremely efficient. And not only that; the template will be typesafe thanks to Rust's compile-time guarantees, so you won't forget to close a tag or an attribute. There is a complete guide to the templating engine that can be found at https://maud.lambda.xyz/.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.250.11