BT

Live Webinar and Q&A: Building AI Agent Evals for High-Stakes Incident Response (Aug 6, 2026) Save Your Seat

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Presentations Million PDFs: Building a Modern Document Infrastructure with Rust and Typst InfoQ 主页 演讲 百万级 PDF:使用 Rust 和 Typst 构建现代文档基础设施

Million PDFs: Building a Modern Document Infrastructure with Rust and Typst百万级 PDF:使用 Rust 和 Typst 构建现代文档基础设施

  • 垂直
  • 水平
  • 全屏
  • 1.25x
  • 1.5x
38:4738:47

Summary摘要

Erik Steiger discusses the operational pain of legacy PDF generation in regulated banking and manufacturing. He explains how transitioning from resource-heavy engines like Puppeteer and LaTeX to a serverless Rust architecture powered by Typst can drop render latencies below 2ms. He shares how applying Git and Docker concepts to template registries ensures ironclad compliance and rapid debugging.Erik Steiger 讨论了受监管的银行和制造业中传统 PDF 生成带来的运营痛点。他解释了如何从 Puppeteer 和 LaTeX 等资源密集型引擎过渡到由 Typst 驱动的无服务器 Rust 架构,从而将渲染延迟降低到 2ms 以下。他还分享了如何将 Git 和 Docker 概念应用于模板注册表,以确保严格的合规性和快速调试。

Bio简介

Erik Steiger is a senior software and AI engineer. He has an academic background in mathematics and previously worked on two AI startups as a technical co-founder. He then gained experience as a technical consultant, collaborating with startups and companies in regulated industries. Currently, he is focusing more on AI research and innovation, supporting deep tech startups in the Munich ecosystem.Erik Steiger 是一位资深软件和 AI 工程师。他拥有数学学术背景,曾作为技术联合创始人参与过两家 AI 初创公司。随后,他积累了技术顾问经验,与受监管行业的初创公司和企业进行合作。目前,他更专注于 AI 研究与创新,支持慕尼黑生态系统中的深度科技初创公司。

About the conference关于会议

InfoQ Dev Summit Munich software development conference focuses on the critical software challenges senior dev teams face today. Gain valuable real-world technical insights from 20+ senior software developers, connect with speakers and peers, and enjoy social events.InfoQ Dev Summit Munich 软件开发大会专注于资深开发团队当今面临的关键软件挑战。从 20 多位资深软件开发人员那里获得宝贵的现实技术见解,与演讲者和同行建立联系,并享受社交活动。

INFOQ EVENTS

Transcript文字记录

Erik Steiger: I will be talking today about PDFs. I know currently we have the era of AI and every other talk has mostly something to do with LLMs. I have to say my background is also in AI and software, but because of the last one-and-a-half years where I've been working in consulting and with companies that do a lot with documents, especially in the compliance area, that has been a pain point of mine. I wrote about it and it struck a nerve. Just to understand where you're sitting or why you are here, I would like to see, who of you came to this talk because you also had something to do with PDFs and have a pain point and it's maybe something you're trying to solve. Maybe some of you are here because it mentioned Rust or Typst, or someone with serverless and so on?Erik Steiger:今天我将讨论 PDF。我知道目前我们处于 AI 时代,几乎每场演讲都与大语言模型(LLM)有关。我必须说,我的背景也是 AI 和软件,但过去一年半里,我一直在从事咨询工作,并与许多处理大量文档的公司合作,特别是在合规领域,这成了我的一个痛点。我写过相关文章,触动了大家的神经。为了了解你们的背景或为什么来到这里,我想看看,在座的各位有多少人是因为自己也处理过 PDF 并有痛点,可能正试图解决它而来到这里的?也许有些人是因为提到了 Rust 或 Typst,或者是因为无服务器架构等等?

Two Experiences - Banking and Manufacturing两种经历——银行与制造业

The two experiences I had last year were one case at the bank who was trying to scale. As you can imagine, like most banks, it's like legacy software and it actually still is COBOL running the show for at least the client where I was. Especially the PDF pipeline that they had was getting too slow. It's like at the point where the customer, you, are buying something like a stock or something and you're waiting for days for the PDF to arrive. It's not only inconvenient, it's regulatorily not allowed. At some point the German Regulatory Institute was like, guys, you cannot do this. They were forced to change. Then they started thinking, what do we do? Obviously, there was this big movement of bringing everything into the cloud. They thought about, yes, can we use AWS Lambda? At this point, I already moved on to another project because I was moved out.去年我有过两次经历,其中一个案例是在一家试图扩展业务的银行。正如你们所能想象的,像大多数银行一样,它使用的是遗留软件,至少在我所在的客户那里,COBOL 仍然是核心。特别是他们拥有的 PDF 流水线变得太慢了。当客户(也就是你们)购买股票之类的东西时,需要等待几天才能收到 PDF。这不仅不方便,而且在监管上是不允许的。在某个时候,德国监管机构表示,你们不能这样做。他们被迫做出改变。然后他们开始思考,我们该怎么办?显然,当时有一个将一切迁移到云端的大趋势。他们考虑过,我们能使用 AWS Lambda 吗?此时,因为我被调离了,我已经转到了另一个项目。

From colleagues who still worked, I heard that it was like one or two years, they were still trying to figure out how can we do PDF rendering in a nice pipeline. I just heard something with Java and pre-compiled, like compiled programs based on every template. I was like, this is going to be a mess. I'm not in contact anymore, but I don't think they have updated since like two years. The second experience was manufacturing. It was not the speed or the latency of every PDF, it was more, how do we manage? Because it was in a regulated industry where you want to know when a truck leaves the facility, it needs the right weighing slip that says, ok, the truck weighs this many tons. What kind of gas, for example, is in there? If it's, for example, medical gas, there are regulatory requirements. In manufacturing, I worked on it for some time, and I can tell you the workflow was somewhat like this.从仍在工作的同事那里,我听说他们花了一两年时间,仍在试图弄清楚如何构建一个良好的 PDF 渲染流水线。我只听说了一些关于 Java 和预编译的内容,比如基于每个模板编译程序。我觉得这会是一团糟。我不再与他们联系,但我认为他们两年来都没有更新过。第二次经历是在制造业。这与每个 PDF 的速度或延迟无关,更多的是关于我们如何管理它。因为在受监管的行业中,你想要知道卡车何时离开设施,它需要正确的称重单,上面写着:好的,卡车重多少吨。里面装的是什么气体?例如,如果是医用气体,就有监管要求。在制造业,我为此工作了一段时间,我可以告诉你,工作流程大致是这样的。

The customer has some problem. The truck driver can't leave because the certificate is just not getting printed. He calls us because we were the service provider for this system. We had first to jump through two VPNs to some remote desktop to see, is it actually an error? Is it a user error? Where's the PDF? Then because of how the system was built up, we had to take a whole backup of the production database, which was like 5, 6, 7 gigabytes, download it through the two VPNs, then put the whole backup file into our test environment, create the valid fake order, because how the system was created, you had to have an order when you want to test if the certificate can be printed, and then try to reproduce it. I felt, because I came from working with startups, that everything was a lot of this, like waiting for a long time.客户遇到了问题。卡车司机无法离开,因为证书就是打印不出来。他打电话给我们,因为我们是这个系统的服务提供商。我们必须首先跳过两个 VPN 进入远程桌面,看看这是否真的是一个错误?是用户错误吗?PDF 在哪里?然后,由于系统的构建方式,我们必须对生产数据库进行完整备份,大约 5、6、7 GB,通过两个 VPN 下载,然后将整个备份文件放入我们的测试环境,创建有效的虚假订单(因为系统构建方式要求在测试证书是否能打印时必须有一个订单),然后尝试重现它。我觉得,因为我来自初创公司,这一切感觉就像是在浪费大量时间。

I came from somewhere where we used modern tools and not these outdated tools. Who of you knows Crystal Reports? Would you speak highly of it? They're like thumbs down in the last row. It was actually really a pain point. For those of you who don't know, it's a software that originated in 1984, which is a very long time. I don't know if we had PCs back there, but seems like it. How it worked is you connected it through like credentials to a database, then it would fetch the schema. There you see like on the left side, there are these little fields where you can then drag and drop it into your PDF. That's how you build it. Now imagine, because we had a lot of factories in different countries, and then there comes like, we have a new factory in Czech. Can you please translate?我来自一个使用现代工具而不是这些过时工具的地方。你们中有谁知道 Crystal Reports?你们会高度评价它吗?最后一排的人都竖起了大拇指(反讽)。这确实是一个痛点。对于那些不知道的人来说,这是一款起源于 1984 年的软件,时间非常久远。我不知道那时我们是否有个人电脑,但看起来确实如此。它的工作方式是,你通过凭据连接到数据库,然后它会获取架构。在那里,你可以看到左侧有这些小字段,然后你可以将它们拖放到 PDF 中。这就是你构建它的方式。现在想象一下,因为我们在不同国家有很多工厂,然后来了个新需求:我们在捷克有个新工厂。你能翻译一下吗?

This means you click on everything you see, you click on everything, copy, paste it into DPL, or your LLM and replace it. This was horrible. It broke me mentally, I feel like. Other tools, if you look around, how else can you generate PDFs? There are other tools, for example, LaTeX. Do some of you come from a scientific background and know LaTeX? You can think of LaTeX like a programming language that spits out the PDF. I know it because from my studies in math, and if you try to like do formulas in Word, it will definitely break you. LaTeX is something where you just have code for how to do a pi sign and so on. Another thing that's used in the industry is something like Puppeteer. This goes more into web development because you render your PDF through web technologies like Chrome, and you just take the PDF and download it.这意味着你点击你看到的每一个东西,点击每一个,复制,粘贴到 DPL 或你的 LLM 中并替换它。这太可怕了。我觉得这在精神上摧毁了我。如果你看看其他工具,你还能如何生成 PDF?还有其他工具,例如 LaTeX。你们中有些人有科学背景并了解 LaTeX 吗?你可以把 LaTeX 想象成一种能吐出 PDF 的编程语言。我了解它是因为我学习数学,如果你尝试在 Word 中处理公式,它肯定会让你崩溃。LaTeX 是一种你只需要代码就能写出圆周率符号等内容的东西。工业界使用的另一种东西是 Puppeteer 之类的。这更偏向于 Web 开发,因为你通过 Chrome 等 Web 技术渲染 PDF,然后直接下载 PDF。

Obviously, it has its drawbacks because you have this whole overhead of creating a headless Chrome instance, like a browser that renders it, and then spits out the PDF. The benefits are obviously you can use talents, or if you know CSS, you can probably get around and build a PDF for you. For LaTeX, for example, you would have to learn how to set a section, a break, and so on.显然,它有其缺点,因为你必须承担创建无头 Chrome 实例(即渲染它的浏览器)的全部开销,然后吐出 PDF。好处显然是你可以使用人才,或者如果你懂 CSS,你可能可以绕过它并为你构建一个 PDF。例如,对于 LaTeX,你必须学习如何设置章节、分页符等等。

Coming from startups, working with code that was managed with Git, where you had something like reproducibility with Docker and CI/CD, I felt like working with documents in the projects that I worked with was super horrible. It was always like, embrace the chaos and just spend four or five hours until it works. I always felt like there is room for improvement. My early Christmas wishlist for this would be obviously speed. If you're like someone who needs to render a million PDFs by the end of the day, for example, if you're a bank or a broker, but also memory consumption because spinning up a whole browser just to print a PDF is probably not the most efficient way. Version control is something that we as developers, we know and also love and are also dependent. I remember back 15 years when you wouldn't know Git and you start writing your files as final version v3 or for some project.来自初创公司,使用 Git 管理代码,拥有 Docker 和 CI/CD 的可重复性,我觉得我在项目中处理文档的方式非常糟糕。总是像是在拥抱混乱,花费四五个小时直到它能运行。我一直觉得有改进的空间。我对此的早期圣诞愿望清单显然是速度。如果你是一个需要在一天结束时渲染一百万个 PDF 的人,例如,如果你是一家银行或经纪人,那么内存消耗也很重要,因为仅仅为了打印 PDF 而启动整个浏览器可能不是最有效的方法。版本控制是我们作为开发人员所了解、喜爱并依赖的东西。我记得 15 年前,当你不知道 Git 时,你开始将文件写为最终版本 v3 或用于某个项目。

In general, the modern developer experience of something like syntax highlighting, cross-platform, it was like Crystal Reports, for example, that I showed earlier, it only works on Windows. It also only works on Windows, not even the ARM version. Where I was working, I tried to use my Mac, but because my Mac is like the new Apple Silicon, which is ARM based, Crystal Reports was having none of it when I tried to use a virtual machine. One big thing was, you saw with the workflow, we spent a long time to download a whole database just to get this connection and try to test it. In the end, we actually just wanted the JSON with the data we want to print.总的来说,像语法高亮、跨平台这样的现代开发体验,比如我之前展示的 Crystal Reports,它只在 Windows 上运行。它甚至只在 Windows 上运行,连 ARM 版本都没有。我工作的地方,我尝试使用我的 Mac,但因为我的 Mac 是新的基于 ARM 的 Apple Silicon,当我尝试使用虚拟机时,Crystal Reports 根本无法运行。有一件大事是,正如你在工作流程中看到的,我们花费了很长时间下载整个数据库,只是为了建立连接并尝试测试它。最后,我们实际上只是想要包含我们想要打印的数据的 JSON。

A Modern Typesetter现代排版引擎

For those who know LaTeX, the past few years, there came a new typesetter from a team in Berlin based on a master thesis. What they share, LaTeX and Typst, they are both typesetters. This means it's not like Word where you get a PDF like what you see. It's more like you have the code where you write, this is my text, and format it please very nicely. You have nice paragraph breaks and so on. You see here on the right side that the syntax resembles like some kind of Markdown DSL where you have these equal signs for a section header and so on. The nice thing is it's more lean than LaTeX. For those who worked with LaTeX and tried to install it on their PC, it's 5 gigabytes for the whole distribution. It's very complicated. There's a lot of dependencies.对于那些了解 LaTeX 的人来说,过去几年,柏林的一个团队基于一篇硕士论文开发了一种新的排版引擎。他们共同点是,LaTeX 和 Typst 都是排版引擎。这意味着它不像 Word 那样,你看到什么就是什么。它更像是你拥有代码,在其中编写“这是我的文本”,并请它非常漂亮地格式化。你有漂亮的段落换行符等等。你可以在右侧看到语法类似于某种 Markdown DSL,你有这些等号作为章节标题等等。好的一点是它比 LaTeX 更精简。对于那些使用过 LaTeX 并尝试在 PC 上安装它的人来说,整个发行版需要 5GB。它非常复杂。有很多依赖项。

Typst is like a modern rewrite where it's just like you download it, which is I think less than 50 megabytes, and then you just compile the file you want to compile into a PDF. It's not only more modern in the developer experience, it's also faster for larger files and it has very nice error messaging. For LaTeX, for example, if you have something that breaks because the variable isn't right, you would get huge error messages and you're like just lost. Here you get really good error messages. My idea was then, ok, so we have Typst, what can we do with it? In our case, what we want to do, we have a template, something on the right, and we have our data that comes from a machine, that comes from customer data from our database. How can we inject it? Because in the original idea of Typst, you would prepare a template, a fixed file, and you would print it into a PDF. We want something in between.Typst 就像是一个现代重写版,你只需要下载它,我想不到 50MB,然后你就可以把你想要编译的文件编译成 PDF。它不仅在开发体验上更现代,而且对于大文件来说速度更快,并且有非常好的错误消息。例如,对于 LaTeX,如果你因为变量不正确而导致某些东西中断,你会得到巨大的错误消息,你会感到迷茫。在这里,你得到了非常好的错误消息。我的想法是,好的,我们有 Typst,我们能用它做什么?在我们的案例中,我们想要做的是,我们有一个模板(右侧的东西),我们有来自机器、来自数据库客户数据的原始数据。我们如何注入它?因为在 Typst 的原始理念中,你会准备一个模板、一个固定文件,然后将其打印成 PDF。我们想要中间的东西。

We want a fixed template that always looks like this. If you have invoices, you always want them to look in the same way. You want to replace the name, the invoice ID, and so on. I wanted something where it was very easy to use as a library in the language you wanted to use. For example, you see down there, in its easiest sense, it's just like render this template. There it's just a string, but obviously, you can get it from the file system, and then just some JSON with the data. That was the goal.我们想要一个看起来总是这样的固定模板。如果你有发票,你总是希望它们以同样的方式显示。你想要替换名称、发票 ID 等等。我想要一种在你想使用的语言中作为库非常容易使用的东西。例如,你在下面看到的,在最简单的意义上,它就像“渲染此模板”。那里只是一个字符串,但显然,你可以从文件系统中获取它,然后只是一些带有数据的 JSON。这就是目标。

Serverless Rust Implementation无服务器 Rust 实现

I wrote a blog post article where I used Typst and bundled it into something that was then deployed on AWS Lambda. It used technologies like AWS Lambda, Terraform to just have infrastructure as code, and it was implemented in Rust. It was like a side project for me to show for me that there's an opportunity for something better to be had than Crystal Reports, what everyone was using. I posted about it, and it got, at least for me, a lot of impressions. Also, I posted on Reddit about it, and there were also some people that definitely felt the pain on generating PDFs, and it surprised me actually a little bit. Also, they're like bad Crystal Reports memories from internship, and it seems like there's obviously a community that shares this pain. The architecture that I went for, for the serverless approach on AWS looked something like this. You would have two Lambdas, two functions.我写了一篇博客文章,其中我使用了 Typst 并将其捆绑到部署在 AWS Lambda 上的东西中。它使用了 AWS Lambda、Terraform 等技术来实现基础设施即代码,并且是用 Rust 实现的。对我来说,这是一个副项目,向我展示了有比每个人都在使用的 Crystal Reports 更好的机会。我发布了关于它的文章,至少对我来说,它获得了大量的印象。我也在 Reddit 上发布了它,确实有一些人感受到了生成 PDF 的痛苦,这实际上让我有点惊讶。此外,他们还有实习期间关于 Crystal Reports 的糟糕记忆,看起来显然有一个社区分享这种痛苦。我为 AWS 上的无服务器方法选择的架构看起来像这样。你会有两个 Lambda,两个函数。

The first one was actually dumb, because it was just taking a request and putting it into a queue. This is the SQS you see there. The second function was bundling Typst into an AWS function, and it was reading the request, getting the template from S3, and printing the PDF and putting it back into S3 bucket. What made this possible, or what it relies heavily on, was cargo-lambda. It's a way for writing Rust-based AWS Lambdas. You can imagine the result looked something like this, that you have your endpoint. You give it the name of the template you want to print, and the data, and what comes out of it was just a confirmation. A, we queued it. It's going to be rendered. Obviously, at this point, there's no retry and error handling. It was just about, can we use Typst to get the performance rendering? We can.第一个实际上很笨,因为它只是接收请求并将其放入队列。这就是你看到的 SQS。第二个函数是将 Typst 捆绑到 AWS 函数中,它读取请求,从 S3 获取模板,打印 PDF 并将其放回 S3 存储桶。使这成为可能,或者它严重依赖的是 cargo-lambda。这是一种编写基于 Rust 的 AWS Lambda 的方法。你可以想象结果看起来像这样,你拥有你的端点。你给它你想要打印的模板名称和数据,出来的只是一个确认。A,我们已将其排队。它将被渲染。显然,在这一点上,没有重试和错误处理。这只是关于,我们能使用 Typst 来获得性能渲染吗?我们可以。

The results were quite astonishing in the sense that it uses way less memory than traditional approaches, like spinning up a whole browser or having this LaTeX. It's below 50 megabytes, and the rendering is below 100 milliseconds, so in the two-digit milliseconds. If you scale this up, it only costs less than 50 cents to render a million PDFs. In comparison, that's like 20 times less than with other approaches.结果非常令人惊讶,因为它使用的内存比传统方法(如启动整个浏览器或使用 LaTeX)少得多。它低于 50MB,渲染时间低于 100 毫秒,即两位数的毫秒数。如果你扩大规模,渲染一百万个 PDF 的成本仅不到 50 美分。相比之下,这比其他方法便宜 20 倍。

This is just speed in a way, and I was also not happy because what this didn't work on was this whole management of PDFs. A nice thing also for you, if you have some side project, I can only recommend put it somewhere, Reddit or so, because they will find the mistakes for you. For example, I didn't know that if you have provisioned concurrency, it generates billing the whole time. There were also some points where I thought, yes, you could actually just remove the three parts and call the Lambda that renders it directly through the Lambda function URL. I did some tracing to find out, what's the actual speed? How much can we get out of it? It turns out if you have some caching in place on the template, you can imagine what Typst does. It gets a template with some variables, and then it lays it out on the PDF, how wide, how big words are.这只是一种速度,我也很不高兴,因为这并没有解决 PDF 的整个管理问题。对你们来说,如果你们有一些副项目,我只能建议把它放在某个地方,Reddit 之类的,因为他们会为你找到错误。例如,我不知道如果你有预置并发,它会一直产生计费。还有一些点,我想,是的,你实际上可以删除这三个部分,并通过 Lambda 函数 URL 直接调用渲染它的 Lambda。我做了一些追踪来找出实际速度是多少?我们能从中得到多少?事实证明,如果你对模板进行了一些缓存,你可以想象 Typst 做了什么。它获取一个带有某些变量的模板,然后将其布局在 PDF 上,多宽,单词多大。

If you just change a little part below where it's like a new number, the rest can stay compiled. You cache it, and you just replace this part. This makes it so fast that on a very small AWS Lambda, you can get a rendering below 2 milliseconds because most of it is cached. Obviously, there were some improvements. For example, the upload to S3 was still one after another, so this could be improved to reduce another 30%. What we got to this point was a rendering engine that works on simple templates. You can imagine the text templates for Typst, you can open them with your code editor, and you can type it. You can put it into Git, and you see Git differences. The input was JSON, so that's something you can very easily mock up. The developer experience was very good because you could compile it on your PC. I could compile it for ARM, for the Linux environment on AWS. The performance was also really great.如果你只是更改下面的一小部分,比如一个新数字,其余部分可以保持编译状态。你缓存它,然后你只需替换这一部分。这使得它非常快,以至于在非常小的 AWS Lambda 上,你可以获得低于 2 毫秒的渲染时间,因为大部分内容都被缓存了。显然,还有一些改进。例如,上传到 S3 仍然是一个接一个,所以这可以改进以减少另外 30%。我们达到这一点的是一个可以在简单模板上工作的渲染引擎。你可以想象 Typst 的文本模板,你可以用你的代码编辑器打开它们,你可以输入它。你可以把它放入 Git,你可以看到 Git 差异。输入是 JSON,所以这是你可以非常容易模拟的东西。开发体验非常好,因为你可以在你的 PC 上编译它。我可以为 ARM、为 AWS 上的 Linux 环境编译它。性能也非常棒。

What Was Lacking?缺少什么?

What was lacking was, what do you do if you're a bank or financial institution, and you want to use the service you already have in your basement? You're not going to use AWS, or maybe you shouldn't. How do you really do version control in these templates? Because creating a Git repository for every template you have is definitely not recommended from my side. Multi-file support was also not there. You can imagine you don't want a massive file where you have like 2,000 to 10,000 lines. You want to structure it. You want to include maybe images, logos, and so on. This was also not in the first version that I worked on. The debugging was also still not great. I thought to myself, what would we need, or where can we draw motivation or inspiration for? It was something like Docker Hub or package managers because they have strict versioning.缺少的是,如果你是一家银行或金融机构,并且你想使用你已经在地下室拥有的服务,你该怎么办?你不会使用 AWS,或者也许你不应该使用。你如何真正对这些模板进行版本控制?因为我绝对不建议为你的每个模板创建一个 Git 存储库。多文件支持也不存在。你可以想象你不想拥有一个 2,000 到 10,000 行的庞大文件。你想要构建它。你可能想要包含图像、徽标等等。这也不在我工作的第一个版本中。调试仍然不是很好。我心想,我们需要什么,或者我们可以从哪里汲取动力或灵感?它类似于 Docker Hub 或包管理器,因为它们有严格的版本控制。

For Docker, for example, you not only know, ok, I have this Docker image for Python, you can even specify by a hash which specific version, which layer do you get. Based on this, I draw together some ideas which I wanted to work on, the first thing is content-addressable storage. png, but you hash the content, you get some hash of random numbers, and then you just take this as your file name. You automatically get deduplication with this. If you now have a lot of templates that use the same logo, because it's the same file, they're not going to be duplicated because it's the same file, so you get the same hash, so you don't get multiple files. Something like text that we know from working with Git where you have branches, I wanted something that's first easy to use and to be human-readable, so to say, I have this invoice at latest, so it's the latest version.例如,对于 Docker,你不仅知道,好的,我有这个 Python 的 Docker 镜像,你甚至可以通过哈希指定你得到哪个特定版本、哪个层。基于此,我整理了一些我想研究的想法,第一件事是内容寻址存储。png,但你对内容进行哈希处理,你得到一些随机数的哈希,然后你只需将其作为你的文件名。你自动获得重复数据删除。如果你现在有很多使用相同徽标的模板,因为它是同一个文件,它们不会被复制,因为它是同一个文件,所以你得到相同的哈希,所以你不会得到多个文件。类似于我们从 Git 工作中知道的文本,你有分支,我想要一些首先易于使用且对人类可读的东西,也就是说,我有这个 invoice at latest,所以它是最新版本。

Maybe you have something like invoice at version 3 for the next rollout for when you have a new corporate design or so. Sometimes, in the regulated industry, you want to be sure that you take the template where the team came and said, we're going to fix it, and I want to be sure that we always take this template. There's also a way to specify a specific template, and not only template because you have to understand, template means not only file, but the bundle, and then we come to the next part. We need a way we can bundle logos, assets like fonts into one package such that the output is always the same. The last part is obviously we want it still to be a nice library that we can use, for example, in a server approach when we later build the next step.也许你有类似 invoice at version 3 的东西,用于下一次推出,当你有一个新的企业设计时。有时,在受监管的行业中,你想要确保你采用团队过来并说“我们要修复它”的模板,并且我想要确保我们总是采用这个模板。还有一种方法可以指定特定模板,而不仅仅是模板,因为你必须理解,模板不仅意味着文件,还意味着捆绑包,然后我们进入下一部分。我们需要一种方法,我们可以将徽标、字体等资产捆绑到一个包中,这样输出总是相同的。最后一部分显然是我们仍然希望它成为一个很好的库,我们可以在例如服务器方法中使用它,当我们稍后构建下一步时。

Just to show you how this could look like, imagine you have an endpoint, like your backend where you manage all your PDF templates. We can say, take this where you see main type. This is like the main entry point. This is the main template, and you can attach files to it and add some metadata. What you get back then is a hash, which is representation of all the data you've put in. If you look at it, how it is stored, you would see that it creates a manifest file with this hash that you got back. This gets stored, and the content looks like this. It's similar to, if you know how Git works, it also builds something like a Merkle tree that we know from cryptocurrencies. It builds like a tree here where we reference the data we will later pull into our template by their hashes. We build a JSON document out of it, and then hash it again.为了向你展示这看起来像什么,想象一下你有一个端点,比如你管理所有 PDF 模板的后端。我们可以说,采用你看到 main type 的这个。这是主要入口点。这是主模板,你可以将文件附加到它并添加一些元数据。你得到的回报是一个哈希,它是你放入的所有数据的表示。如果你看一下它是如何存储的,你会看到它创建了一个带有你得到的回报的哈希的清单文件。这被存储,内容看起来像这样。它类似于,如果你知道 Git 是如何工作的,它也构建了类似于我们从加密货币中知道的 Merkle 树的东西。它在这里构建了一棵树,我们通过它们的哈希引用我们稍后将拉入模板的数据。我们从中构建一个 JSON 文档,然后再次对其进行哈希处理。

When I say I want a template starting with 39a9, this means, get me these files and put them into a bundle and then render it. If we work now with reference, because you don't always want to remember the whole hash, so we can also create references. This only means that latest points to this hash, and this hash is again this manifest file. The whole flow looks like, if I type in invoice latest, we look at the reference, we take the hash, we take the manifest, and then later pull from storage all the blob files, can be the image, can be the main template.当我说我想要一个以 39a9 开头的模板时,这意味着,获取这些文件并将它们放入一个捆绑包中,然后渲染它。如果我们现在使用引用工作,因为你不想总是记住整个哈希,所以我们也可以创建引用。这只意味着 latest 指向这个哈希,而这个哈希又是这个清单文件。整个流程看起来像,如果我输入 invoice latest,我们查看引用,我们获取哈希,我们获取清单,然后稍后从存储中拉取所有 blob 文件,可以是图像,可以是主模板。

A New Architecture新架构

Coming back to the workflow, this meant that when our customer would call us and say, this certificate that we tried to print, it didn't work, this means, because we store not only the template, but also the data, we could look up at renders we did that contained, in this case, ID of the order. We could look up and then we see there's this failed render entry where we get the render ID, we get the template reference, we even get a hash to the data that was used. If you store also the data that was used to render, you could look up, maybe they forgot something. In this case, maybe they probably forgot the expiry date. This means we can reproduce failed renders, like take the data that was used, download it, inspect it, test it, and test it so long until you get it right. To zoom out a bit, the thing I did with the AWS serverless was mainly a rendering engine.回到工作流程,这意味着当我们的客户打电话给我们并说,我们尝试打印的这个证书,它不起作用,这意味着,因为我们不仅存储模板,还存储数据,我们可以查看我们包含的渲染,在这种情况下,订单的 ID。我们可以查看,然后我们看到有这个失败的渲染条目,我们得到渲染 ID,我们得到模板引用,我们甚至得到用于渲染的数据的哈希。如果你还存储用于渲染的数据,你可以查看,也许他们忘记了什么。在这种情况下,也许他们可能忘记了到期日期。这意味着我们可以重现失败的渲染,比如获取使用的数据,下载它,检查它,测试它,并测试它直到你弄对为止。稍微缩小一下,我用 AWS 无服务器做的事情主要是渲染引擎。

You can go back and build the registry on top using modern techniques we know from something like Docker Hub or package managers, where we have template management. It's more compliant, and you get analytics. Because if you have a large factory that prints a lot of documents, you also want to know which one failed in the last week and then inspect why. Then, if you have something like this, it's pretty easy to build a server on top that you can then horizontally and vertically scale. You have parallelization that pretty nicely uses all your CPU cores without much of a headache on your side. You get strong caching, which reduces the latency even further. You just have a modern data interface where you can use something like JSON.你可以回去使用我们从 Docker Hub 或包管理器等东西中知道的现代技术构建注册表,我们在那里进行模板管理。它更合规,并且你获得分析。因为如果你有一个打印大量文档的大型工厂,你也想知道上周哪一个失败了,然后检查原因。然后,如果你有这样的东西,在上面构建一个服务器非常容易,然后你可以水平和垂直扩展它。你拥有并行化,它非常漂亮地使用了你所有的 CPU 核心,而不会给你带来太多的头痛。你获得强大的缓存,这进一步降低了延迟。你只是拥有一个现代数据接口,你可以使用 JSON 之类的东西。

To give you even like where this could lead or how you can think of it is that you can even put something, I said, like we had this keynote, and this would be like the pre-MCP, like still a normal UI, where you would see the past renders that your faculty did, which one failed, why they failed. You can download the PDF, you can inspect the data. Coming back and thinking where the old tools were, like LaTeX being very heavy, very big dependencies, you would need 5 gigabytes to install it. The Docker images to install LaTeX is huge. In this case, if you bundle it, it's less than 100 megabytes. Then Crystal Reports, it still was dependent on having an active database connection. You also don't need that here. You just have your template and you give it some data. Also, like Puppeteer, I don't know who of you have tried to render something with that?为了给你甚至像这可能导致什么或你可以如何思考它,你可以甚至放一些东西,我说,就像我们有这个主题演讲,这将是像预 MCP,仍然是一个正常的 UI,在那里你会看到你的学院所做的过去渲染,哪一个失败了,为什么它们失败了。你可以下载 PDF,你可以检查数据。回到并思考旧工具在哪里,比如 LaTeX 非常重,非常大的依赖项,你需要 5GB 来安装它。安装 LaTeX 的 Docker 镜像非常大。在这种情况下,如果你捆绑它,它不到 100MB。然后 Crystal Reports,它仍然依赖于拥有一个活动的数据库连接。你在这里也不需要那个。你只需要你的模板,你给它一些数据。此外,像 Puppeteer,我不知道你们中有谁尝试过用它渲染东西?

The nice thing is you get these guarantees that you can design it with CSS, but it consumes a lot of memory because you have long cold start times. If you try to use something like Puppeteer on AWS Lambda, it's going to be quite slow because you need at least a second to start the browser. This was at least the project for me where I saw that you could use modern tooling that was originally meant for scientific work. Typst was meant to print scientific papers. Because of how performant it is, you can use it also for document generation in the industry. If you now take then modern tooling that we see from Docker, from Git, from version control, we even get something where we have strong compliance guarantees. We can manage it very nicely, where we always get the PDF that we want in the beginning.好的一点是你得到这些保证,你可以用 CSS 设计它,但它消耗大量内存,因为你有很长的冷启动时间。如果你尝试在 AWS Lambda 上使用 Puppeteer 之类的东西,它会非常慢,因为你需要至少一秒钟来启动浏览器。这至少是对我来说的项目,我看到你可以使用最初用于科学工作的现代工具。Typst 旨在打印科学论文。由于它的性能,你也可以在工业中的文档生成中使用它。如果你现在采用我们在 Docker、Git、版本控制中看到的现代工具,我们甚至得到了一些东西,我们有强大的合规保证。我们可以非常好地管理它,我们总是得到我们一开始想要的 PDF。

Resources资源

For those of you who are interested or you think this could be relevant for you, all the code and all that I mentioned is open source. Even the original Typst PDF renderer is open source. If it's something for you, look into it and reach out if you have something.对于那些感兴趣或认为这可能与你相关的人,我提到的所有代码和所有内容都是开源的。甚至原始的 Typst PDF 渲染器也是开源的。如果这对你来说是某种东西,看看它,如果你有什么东西,请联系。

Questions and Answers问答

Participant 1: Can you show an example of this document where you did this benchmark with this 1 million PDFs?参与者 1:你能展示一个你用这个 100 万个 PDF 进行基准测试的文档示例吗?

Erik Steiger: Yes. I don't know if your question goes into if it was too simple?Erik Steiger:是的。我不知道你的问题是否在于它是否太简单了?

Participant 1: Yes. Because my experience is, for example, if you will look at the poster here. The poster consists of six texts and seven images and some vector graphics, and it depends on how many elevens you have and how complicated they are, and how many fonts you need.参与者 1:是的。因为我的经验是,例如,如果你看这里的海报。海报由六个文本和七个图像以及一些矢量图形组成,它取决于你有多少个 11 以及它们有多复杂,以及你需要多少字体。

Erik Steiger: The template I used looked like this. I tried to actually have an honest comparison. I tried to design it as a trade confirmation for a bank. I know you're more in the invoicing?Erik Steiger:我使用的模板看起来像这样。我确实尝试进行诚实的比较。我尝试将其设计为银行的交易确认书。我知道你更多是在发票方面?

Participant 1: Yes. It looks ok. It's one page with a lot of text, some lines, some vector.参与者 1:是的。看起来还可以。这是一页有很多文字、一些线条、一些矢量的页面。

Erik Steiger: Exactly.Erik Steiger:正是。

Participant 1: It's no images. The top left is text or image?参与者 1:没有图像。左上角是文本还是图像?

Erik Steiger: I think this was a PNG file, yes. There you see most of the data that probably changes, was randomized. Most of the stuff you see, for example, the table had to be re-layout. Sometimes the results even had two pages based on how long the table were.Erik Steiger:我想这是一个 PNG 文件,是的。在那里你看到大部分可能改变的数据,是随机化的。你看到的大部分东西,例如,表格必须重新布局。有时结果甚至有两页,基于表格有多长。

Participant 2: The comparison to LaTeX, because on the Docker container size, I couldn't agree more. It's a hell of a thing, LaTeX in a Docker container. Did you run it speed-wise against LaTeX, out of curiosity?参与者 2:与 LaTeX 的比较,因为在 Docker 容器大小上,我完全同意。这真是太糟糕了,Docker 容器中的 LaTeX。出于好奇,你是否在速度方面针对 LaTeX 运行过它?

Erik Steiger: No. I remember from my times using it back then. I think the fastest you get is 300 milliseconds to 500 milliseconds. Speaking on that, if you say that, it's not like you know which program to use, because LaTeX is huge. They're different, XeTeX and LuaLaTeX. I think to do a comparison, you can optimize it very heavily. If I would build a PDF rendering engine back then, 5 years ago, I would use LaTeX. I also saw at stock agencies that they were using it with MATLAB, but I always felt it's not very modern because of the big compilation size and the error messaging that was [inaudible 00:32:25], in a way. If you're, for example, interested, there are still the blog posts about it on my website that talks a bit more about the AWS Lambda setup and how you can compile a Rust program into an AWS Lambda function, and also do with the Terraform.Erik Steiger:没有。我记得我当时使用它的时光。我认为你得到的最快速度是 300 毫秒到 500 毫秒。说到这一点,如果你那样说,并不是你知道使用哪个程序,因为 LaTeX 太大了。它们是不同的,XeTeX 和 LuaLaTeX。我认为做一个比较,你可以非常重地优化它。如果我 5 年前构建一个 PDF 渲染引擎,我会使用 LaTeX。我也在股票代理机构看到他们使用它与 MATLAB,但我总是觉得它不是很现代,因为巨大的编译大小和错误消息是 [听不清 00:32:25],在某种程度上。如果你,例如,感兴趣,我的网站上仍然有关于它的博客文章,谈论更多关于 AWS Lambda 设置以及如何将 Rust 程序编译成 AWS Lambda 函数,以及也用 Terraform 做。

Participant 3: Is everything here that you instruct open source? Every tool or you have something that you may need to pay a license?参与者 3:你在这里指导的一切都是开源的吗?每个工具还是你有一些可能需要支付许可的东西?

Erik Steiger: Everything is open source, so that's the repo where most of the crates are. It's split into three crates, the main library that builds around Typst. Then you have the registry, which works with all this manifest, creating the hashes. Then the last one is more or less just a topper where you have a server. All of it is open source. Like I mentioned, it heavily relies on the PDF rendering engine types. If you want to have a go at it, feel free.Erik Steiger:一切都是开源的,所以这是大多数 crate 所在的 repo。它分为三个 crate,围绕 Typst 构建的主库。然后你有注册表,它处理所有这些清单,创建哈希。然后最后一个或多或少只是一个 topper,你有一个服务器。所有这些都是开源的。就像我提到的,它严重依赖 PDF 渲染引擎类型。如果你想尝试一下,请随意。

Participant 3: Yes, I'm using it mainly from Java Enterprise work, I'm using just for inputs. We've come close to 100 milliseconds per rendering, because you can now use caching and browsing enables you to start it very fast, not to wait for the VM to start up, but some [inaudible 00:34:21] is still out of reach.参与者 3:是的,我主要从 Java Enterprise 工作中使用它,我只是用于输入。我们已经接近每渲染 100 毫秒,因为你现在可以使用缓存,浏览使你能够非常快地启动它,而不是等待 VM 启动,但一些 [听不清 00:34:21] 仍然遥不可及。

Erik Steiger: Depending on how complicated it is, with caching, you get sub-10 millisecond.Erik Steiger:取决于它有多复杂,通过缓存,你可以获得低于 10 毫秒。

Participant 3: Usually, if there are like large PDFs with all the disclaimers and all the information with this from the customer, and stuff like that. It's large like that.参与者 3:通常,如果有像大型 PDF 那样带有所有免责声明和所有信息,来自客户,诸如此类。它就是那么大。

Erik Steiger: Was speed your main problem?Erik Steiger:速度是你的主要问题吗?

Participant 3: Amount of PDFs is my main problem, so very large amount of PDFs.参与者 3:PDF 的数量是我的主要问题,所以非常大量的 PDF。

Erik Steiger: To generate them in time.Erik Steiger:及时生成它们。

Participant 3: Yes.参与者 3:是的。

Erik Steiger: Yes, similar to the bank. Yes, try it.Erik Steiger:是的,类似于银行。是的,试试看。

Participant 4: My question was like, so you have text in JSON form, then you have a hash of text in the registry of it, you map it to a template, and then you render the PDF type. That's where I'm like, can you go in reverse? You have the PDF, then you get the template which was used, then you get the JSON back. Is that a possibility to come back to it?参与者 4:我的问题是,所以你有 JSON 形式的文本,然后你在它的注册表中有一个文本的哈希,你将其映射到模板,然后你渲染 PDF 类型。这就是我像的地方,你能反向操作吗?你有 PDF,然后你得到使用的模板,然后你得到 JSON。回到它是一种可能性吗?

Erik Steiger: You mean you rendered a bunch of PDFs, and then the customer comes back to you with a PDF and says, can you check when it was rendered and with which data?Erik Steiger:你的意思是,你渲染了一堆 PDF,然后客户带着 PDF 回到你身边并说,你能检查它是什么时候渲染的以及使用什么数据吗?

Participant 4: Yes.参与者 4:是的。

Erik Steiger: If you have it digitally, probably yes, because you can imagine that at some point you process or you generate the PDF. You could store this PDF, or at least the hash in your bucket, and then you would know which manifest was used to render it, and from there you can derive all the rest. It's interesting for compliance areas where you want to know which version was used.Erik Steiger:如果你以数字方式拥有它,可能可以,因为你可以想象在某个时候你处理或生成 PDF。你可以将此 PDF 或至少哈希存储在你的存储桶中,然后你就会知道哪个清单用于渲染它,从那里你可以推导出其余所有内容。这对于合规领域很有趣,在那里你想要知道使用了哪个版本。

Participant 4: Where I work, we do a lot of PDF processing, so we need to figure out exactly what's in the PDF, essentially, and then you go back to a JSON format for that, and then we create, let's say, more PDFs from that. It's like a circle that you need to do. I was just wondering if you can, let's say, maintain similar hashes, then maybe you can figure out what's the closest hash, and say, ok, this is maybe the format that was used.参与者 4:我工作的地方,我们做很多 PDF 处理,所以我们需要弄清楚 PDF 中到底有什么,本质上,然后你回到 JSON 格式,然后我们创建,比如说,更多的 PDF。这就像你需要做的圆圈。我只是想知道你是否可以,比如说,维护类似的哈希,那么也许你可以弄清楚什么是最近的哈希,并说,好的,这也许是使用的格式。

Erik Steiger: That's a bit different. If it's visually just a little bit different, even if there's just something different that's not visible in the PDF, this would change the hash. What you're talking was like visual comparison.Erik Steiger:那有点不同。如果它在视觉上只是有点不同,即使有一些不同的东西在 PDF 中不可见,这也会改变哈希。你谈论的是视觉比较。

Participant 5: In my experience, when you design some documents for instance invoices, the customer often asks for very specific layouts and something. My question would be if you had to set some kind of boundaries or if the Typst was powerful enough to create everything in custom mode?参与者 5:根据我的经验,当你为发票等设计一些文档时,客户经常要求非常具体的布局和某些东西。我的问题是,如果你必须设置某种边界,或者 Typst 是否足够强大以在自定义模式下创建所有内容?

Erik Steiger: I don't know if Typst does animation, and I know PDF can do animation. I don't know if you want to go that far. I think for most layouts that we see in PDFs, it's possible. Because we are obviously using Typst, you could look at the examples they give. Most of them are from scientific nature, but you can do graphs. You can bring in images. It's actually quite powerful. I would say yes to your question, if it's not very exotic.Erik Steiger:我不知道 Typst 是否做动画,我知道 PDF 可以做动画。我不知道你是否想走那么远。我认为对于我们在 PDF 中看到的大多数布局,这是可能的。因为我们显然在使用 Typst,你可以看看他们给出的例子。它们大多数是科学性质的,但你可以做图表。你可以引入图像。它实际上非常强大。如果它不是很奇特,我会对你的问题说是。

 

See more presentations with transcripts查看更多带有文字记录的演讲

 

Recorded at:

Jun 29, 20262026 年 6 月 29 日

Related Sponsors相关赞助商

BT