首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 汽车 游戏 社会热点 开源推荐 医疗健康 归档 标签 关于

Zig 中的类型安全 HTML 模板

摘要

I’ve done a lot of web development over the years. I started around the year 2000, just after PHP 3.0 was released and started taking over the web world. I’ve used all kinds of approaches for generati...

the and with was all web have that want development
2026-10-12 1 阅读 约7分钟阅读 lukaslalinsky
分享:
字号:
多年来我做了很多网络开发工作。我是在 2000 年左右开始的,就在 PHP 3.0 发布并开始占领网络世界之后。我使用过各种生成 HTML 的方法:原始 PHP、Python 中的字符串连接、PHP 中的 Smarty 模板、Perl 中的 Template Toolkit 以及 Python 中的 Jinja/Django 模板。然后,随着世界转向 SPA 和 JavaScript 框架,我停止了前端工作。两年前,我选择了 Zig,我从未想过我会考虑使用如此低级的语言进行 Web 开发。但当我用 zio 和 Dusty 构建自己的生态系统时,我意识到这并不是那么牵强。我为 API 后端构建了这些库,其中输出是 JSON 或 MessagePack,但后来我发现,通过正确使用 arena 分配器,即使是 Web 开发实际上也是可以管理的,因为您不需要记住取消分配通常涉及的所有字符串。借助 Zig 的 comptime,您可以构建非常高级的接口,而不会失去性能优势。在 htmx 或 Datastar 的帮助下,您甚至可以在不接触 JavaScript/TypeScript 的情况下构建 SPA,我向自己保证我永远不会这样做。也就是说,仍然缺少一件事:模板。字符串连接不是一个选项,我不想回到 2000 年之前的 CGI 时代。我对模板库有一些要求:它必须是类型安全的,所有输入都在编译时键入并检查。我一生中已经足够多地处理动态语言了,我不想再处理运行时模板错误了。它必须要快。没有分配,没有中间状态,只需将输出直接写入std.Io.Writer。它需要有安全的默认值。我不想再处理 XSS,所以默认情况下所有输入都必须转义。它应该仍然像编写 HTML 一样。我不想要一个基于 Zig 的 DSL,这样我就必须不断地与之斗争。我找不到任何可以满足所有这些要求的解决方案。然后我看到了 Ziex,我很惊讶。我从来没有想到 JSX 方法可以在 JavaScript 之外完成。 Nurul Huda 在 Zig 中成功打造的开发者体验对我来说是难以想象的。它并不能直接满足我的需求,因为我不需要 WASM 框架,但是它的语法和他将 Zig 代码集成到模板中的方法给了我一些想法。然后,经过进一步的研究,我发现了 Templ for Go,这对我来说很明显我想要构建什么。那么,让我介绍一下 zt (我不擅长命名,抱歉)。这是 Temple 对 Zig 的改编。在 zig build 期间,模板将被解析并转换为 Zig 代码。这意味着您可以直接从应用程序代码导入它们,而且,也许更重要的是,模板可以导入您的应用程序代码。因此,所有参数都可以完全键入。如果某些内容无法渲染,Zig 编译器会告诉您。生成的代码相当简单,它所做的只是写入 std.Io.Writer 。您可以选择直接写入套接字或将输出累积在缓冲区中。模板如下所示:const User = @import ("../models.zig")。用户; pub templ 布局 ( title : [] const u8 ) { < html > < head > < title > { title } < body > @children } pub templ HomePage(user:?User){@Layout("Home"){if(user)|你| { < h1 > 欢迎回来,{ u . name } ! < a href = "/users/{u.id}" > 您的个人资料 } else { < h1 > 欢迎,访客! < a href = "/login" > 登录 } } } 以下是如何在 Zig 代码中使用它: const std = @import ( "std" ); const User = @import ("models.zig").用户; const 页面 = @import("templates/pages.zig"); pub fn main(init:std.process.Init)! void { var buf : [ 4096 ] u8 = 未定义 ; var stdout = std .伊欧。文件 。标准输出()。 writer ( init . io , & buf ); const w = & 标准输出。界面 ;常量用户:用户= . {。 id = 1 , .名称 =“卢卡斯”};尝试页面。主页。渲染 ( . { 用户 }, w );尝试一下。冲洗();如果你想在 Dusty 中使用它来渲染 HTML 页面,你只需这样做:尝试 res 。 render(.html,pages.HomePage,.{user});附带说明一下,如果您在 std.Io 取消问题的某个地方使用相同的模式,上面的主要代码片段在错误处理方面有一个非常不明显的错误。我可能会写一篇关于它的博客文章,但如果您有兴趣,请查看此 Ziggit 线程。 Dusty 中包装 std.Io.Writer 处理的渲染函数解决了这个问题。默认情况下,所有动态值在文本和属性中都是 HTML 转义的,并且还会检查 href 或 src 等 URL 属性中的值是否存在危险方案。如果您确实需要输出原始 HTML,则必须使用 {!value} 显式请求,这样很容易在模板中找到。解析器还要求所有元素正确关闭,这样您就不会意外地生成损坏的标记。它不能保护您免受所有攻击,但它可以消除最常见的 XSS 来源。我最喜欢的是
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱