#html #dynamic #markup #template #render-template

nightly stpl

使用Plain-Rust的超级模板(html等),无需文本文件

6个版本 (破坏性更新)

使用旧的Rust 2015

0.5.0 2017年12月31日
0.4.0 2017年12月31日
0.3.1 2017年12月7日
0.2.0 2017年12月4日
0.1.0 2017年12月3日

#233 in 模板引擎

MPL-2.0/MIT/Apache-2.0

41KB
860

Travis CI Build Status Gitter Chat

stpl

stpl - Rust的超级模板库

stpl 是一个仅使用Plain-Rust的模板库,具有一些实用的特性和功能。

主要思想

stpl 中没有魔法宏或DSL,也没有笨拙的带有奇怪语法的文本文件。一切都是正常的、易于理解的Rust代码。

让我们通过一个来自试点项目的实际例子来看看:一个基于Bootstrap的UI的HTML基本骨架模板。

pub fn base<C: Render + 'static>(data: &Data, content: C) -> impl Render {
    (
        doctype("html"),
        html((
            head((
                meta.charset("utf-8"),
                meta.name("viewport").content("width=device-width, initial-scale=1, shrink-to-fit=no"),
                meta.name("description").content(""),
                meta.name("author").content("Dawid Ciężarkiewicz"),
                title(data.title.clone()),
                (
                    link.rel("icon").href("/static/favicon.ico"),
                    link.rel("stylesheet").href("/static/theme/flatly/bootstrap.min.css"),
                    link.rel("stylesheet").href("/static/theme/starter-template.css"),
                )
            )),
            body((
                navbar(data),
                main
                    .id("main")
                    .role("main")
                    .class("container mb-5")(
                    content,
                ),
                (
                script.src("https://code.jquery.com/jquery-3.2.1.min.js").crossorigin("anonymous"),
                script.src("https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js")
                    .integrity("sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh")
                    .crossorigin("anonymous"),
                script.src("https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js")
                    .integrity("sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ")
                    .crossorigin("anonymous"),
                script.type_("text/javascript")(
                    raw(include_str!("white-icon.js"))
                ),
                )
            ))
        ))
    )
}

这只是一个函数。没有魔法,没有宏,没有涉及文本文件。整个模板就像正常的Rust代码一样,使用 rustfmt 格式化。

该函数接受参数

  • data: Data 包含如何“填充空白”的信息,以及
  • content: Render - 作为主页内容的子模板值。

该函数返回一个 Render 值,可以将其渲染为字符串或字节,或与其他模板组合。该值基本上是一个嵌套了许多其他 Render 值的大元组。 Render 为许多标准类型实现了,可以为新类型实现或使用函数/闭包生成。

用户可以自由使用任何Rust语言原语来生成他们的模板,并以任何适合他们的方式组织它们之间的关系。

动态渲染

虽然 stpl 生成Rust代码且不涉及“运行时解析”,但它支持在单独的进程中实际渲染,从而在运行时热交换模板。这对于加速开发非常有用。

基本机制是

  • 序列化模板数据,并将其发送到子进程
  • 从子进程读取渲染的模板

在子进程中

  • 确定要使用的模板
  • 从stdio读取序列化的数据并将其反序列化
  • 渲染模板并将输出输出到stdout

在此方案中,父进程和子进程的二进制文件可以是相同的(参见 render_dynamic_self)或不同的(参见 `render_dynamic`)。

使用相同的二进制文件更方便。使用单独的二进制文件需要以某种方式组织项目,但可以极大地提高迭代时间。

以下内容摘自 Cargo.toml,以支持在单独的二进制文件中进行动态渲染


[[bin]]
name = "template"
path = "src/main_template.rs"

[[bin]]
name = "webapp"
path = "src/main.rs"

这两个程序共享许多模块(例如模板和数据结构),但 main_template 不需要包含像 rocketdiesel 和类似的重量级库,因此编译速度更快。

在我们的测试中,以调试模式构建主网络应用需要 11.4 秒,而重新编译所有模板则要快得多

$ cargo build --bin template
Compiling webapp v0.1.0 (file:///home/dpc/lab/rust/webapp/web)
Finished dev [unoptimized + debuginfo] target(s) in 1.04 secs

优点

  • 健壮:模板生成可以复用任何现有的代码和数据结构
  • 方便:Rust 工具可以像处理其他任何代码一样处理纯 Rust 模板;rustfmt 负责格式化,错误信息以正常错误消息的形式出现等。
  • 快速:编译器优化模板代码,使其只包含写入渲染模板数据的必要逻辑;不涉及解析过程
  • 快速迭代:使用动态加载,可以在不等待 Rust 编译器构建整个应用程序的情况下重新加载模板

缺点

  • nightly-仅:此库依赖于一些不稳定的特性(主要是 impl trait
  • 不成熟和不完整:此库仍在开发中,并将随着时间的推移而成熟。

如何开始

你很可能对阅读 html 模块文档感兴趣

帮助

请参阅 ./playground 子目录中的示例用法。

许可证

stpl 适用于:MPL-2.0/MIT/Apache-2.0

依赖关系

~520–800KB
~17K SLoC