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 模板引擎
41KB
860 行
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
不需要包含像 rocket
、diesel
和类似的重量级库,因此编译速度更快。
在我们的测试中,以调试模式构建主网络应用需要 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