博客

gPdf vs DocRaptor:为什么边缘 PDF 生成胜过 HTML 转 PDF

DocRaptor 在托管后端用 Prince 把 HTML 转成 PDF。gPdf 在边缘把结构化 JSON 直接生成 PDF。价格相差 18×。这不是钓鱼价。

DocRaptor 是个不错的产品。它把 Prince——HTML 转 PDF 的金标准引擎——包装成托管 REST API,配上重试、异步任务、还算好的文档。它存在十多年,对很多团队来说是「我不想自己跑 Prince」的明显选择。

我们是另一种产品形态。gPdf 根本不接受 HTML——它接受结构化 JSON,并在 Cloudflare 边缘直接生成 PDF。100K 页/月的标价差距是 $5/月(gPdf Basic) vs $89/月(DocRaptor Basic)——大约 18×。这个差距不是首发优惠,是结构性的。本文讲为什么架构会产生这个价格,以及两种工具各自适合哪里。

两种架构并排看

DocRaptor (HTML → PDF)gPdf (JSON → PDF)
输入HTML + CSS(带 Prince 的 paged-media 扩展)DocumentRequest JSON
渲染器Prince(编译型 C++ 引擎)自研 Rust 引擎,编译为 WebAssembly
部署DocRaptor 中心化服务器(美国机房)Cloudflare Workers,每个 CF colo(300+ 城市)
冷启动服务端 worker poolV8 isolate 启动,个位数毫秒
单次渲染算力HTML/CSS 布局过程 + Prince 分页直接排版,无布局解读过程
单次 p50~250–800 ms wall-clock(含网络)~3–8 ms(含网络)
输出确定性高(Prince 成熟)字节一致(同 JSON → 同字节)

如果你把这两列读成「通用 HTML 打印机」vs「专为文档构建的生成器」,你已经理解了架构决策。其他一切(延迟、成本、甚至功能清单)都是这一选择的结果。

Prince 税

Prince 是的。它也在做大多数发票/收据/运单工作流不需要的事:为用户可能扔过来的任意 HTML 实现 CSS Paged Media——分页规则、running header、脚注、交叉引用、生成内容框。

这种通用性有运行时成本。要分页任意 HTML 文档,引擎必须:

  1. 解析并验证 HTML
  2. 解析并解算 CSS 级联(可能含 Prince 自己的扩展)
  3. 构建渲染树
  4. 跑多遍布局(尤其是跨页表格、平衡列)
  5. 跨页解算交叉引用
  6. 输出 PDF 对象

大多数过程是接受 HTML 作为输入的代价。如果你的输入本来就是结构化数据(几乎总是——你的发票在被包成 HTML 之前就以 JSON 对象形式存在),你每次生成 PDF 都在为这些过程付算力和延迟,而它们并不会提升最终输出。

gPdf 完全跳过布局解读这一步。JSON DocumentRequest 已经用结构化方式指定页面布局——{ pages: [{ size, elements: [...] }] }。渲染器排字、确定性分页、输出 PDF。没有 CSS 级联可解算、没有浮动布局可计算、没有交叉引用解算过程。

结果:DocRaptor 上 ~300 ms 的同一张单页发票,在 gPdf 上 ~3 ms。我们快不是因为写了一个更快的 Prince——而是因为我们不做 Prince 大部分要做的事。

“便宜得不真实” 是真实的采购异议

直接讲清楚,因为每次 B2B 销售都会被问到。

“$5/月,10 万次渲染。DocRaptor 是 $89。Anvil 是 $0.10/PDF(同量是 $10,000)。你们到底有什么问题?”

我们能这么收费的三个诚实原因:

1. 我们不跑浏览器

DocRaptor 把 Prince 基础设施摊销到客户身上。gPdf 摊销的是一个 Cloudflare Worker——Workers Bundled 大约 $0.50/百万次请求。JSON 形状的输入,我们的渲染器单次大约 1.5 ms CPU。叠 50% 毛利还在「美分级别每千次」区间。算术就是价格。

2. 我们不跑控制面

没有异步任务、没有回调、没有重试队列、没有文档存储、没有预览链接 UI、没有多租户数据库。每次渲染都是单次往返到无状态函数再返回。这去掉了大多数「PDF API」公司需要承担的运维面——也就是让他们价格变高的那部分。

3. 这模型自动筛掉我们会亏钱的工作负载

如果你的文档真的需要 HTML 转 PDF(60 页法律合同、复杂 CSS Grid 报告),你第一小时就会发现 JSON 模型不适合,然后转向 DocRaptor。我们不需要为这些工作负载防御性定价,因为它们会自然流向更合适的工具。我们只需要为「结构化数据→文档」这类长尾但边界清晰的工作负载定价——单次渲染成本本来就极小。

合起来:$5/100K 不是赔本赚吆喝,而是真实的成本+毛利。我们能长期保持这个价格,因为底层算力就是这么便宜,只要不把浏览器放进生成链路。

DocRaptor 是正确选择的场景

我们尽量不写自利对比。DocRaptor 真正胜出的几种情况:

  • 你的输入是你不完全控制的 HTML。 用户生成的报告、第三方模板、CMS 渲染的 Markdown 转 HTML。你不想为任意输入写 JSON 映射器。
  • 你需要 Prince 支持的 CSS Paged Media 特性。 每章 running header/footer、复杂脚注 reflow、命名页选择器、生成的目录、索引。gPdf 对常见子集有结构化对等品,但如果你住在 @page :left 选择器里,Prince 是你的朋友。
  • 你的内容团队写 HTML/CSS,不写 JSON。 别强迫非工程团队用 JSON 撰写工作流。他们会恨你。
  • 异步 + 回调 + 文档存储即服务。 DocRaptor 存生成的 PDF 并给你签名 URL 用于交付。gPdf 严格无状态——你的代码自己存结果。

如果你在以上任一桶里,留在 DocRaptor。 它是对的工具。

gPdf 是正确选择的场景

镜像反过来:

  • 你的输入已经是结构化数据(数据库行、JSON API 载荷、队列消息)。
  • 延迟重要——交互式结账流、实时面单打印、按需对账单生成。
  • 你在乎字节一致可复现用于测试/审计/电子发票留存。
  • 在几千次/月以上的任何量级你都对成本敏感。
  • 你需要条码(GS1-128、QR、Data Matrix、PDF417、Aztec、MaxiCode)做亚毫米精度——Prince 技术上支持 SVG 条码,但通过 HTML/CSS 做到 0.1 mm 整体长度精度并不简单。
  • 你需要 PDF/A(1b/2b/3b/4)或 Factur-X / ZUGFeRD 附件做合规。
  • 你宁愿不跑「JSON → HTML → PDF」管线——既然可以跑「JSON → PDF」管线。

迁移是机械活,不是战略活

常见的担心:「换工具意味着重写所有模板。」通常不是。大多数 HTML 转 PDF 模板是 20% 布局(一次性变成 JSON 结构)+ 80% 数据插值(无论渲染器接什么都一样)。

实操路径:

  1. 一种文档类型迁移。从最大量的开始——节省最大、爆炸半径最小。
  2. 拿 HTML 模板的数据接口(它插值的变量),写个小 mapToDocumentRequest(data) 函数。
  3. 在线体验中迭代,直到输出符合预期。
  4. 生产 A/B:路由 5% 流量到 gPdf 跑两周。Diff PDF。比账单。
  5. 按数据决定,不按感觉。

我们见过团队一个 sprint 内做完,下个月把 90% PDF 账单收进口袋。也见过团队意识到自己工作负载其实是 HTML 转 PDF 场景,留在 DocRaptor——带着我们的祝福。

一句话

DocRaptorgPdf
擅长任意内容的 HTML → PDF结构化文档的 JSON → PDF
100K 页/月价$89$5
p50 渲染250–800 ms3–8 ms
边缘部署❌ 中心化✅ 300+ Cloudflare colo
异步 + 存储✅ 含❌ 设计上无状态
PDF/A + Factur-X⚠️ 通过 Prince 扩展✅ 内置

如果你的文档本质上是结构化数据,只是套了一层 HTML,你就在为一个不该存在的转换环节付费。来在线体验试试——用 JSON 描述你的一张发票,在浏览器里 5 ms 内生成 PDF,看看差距是否符合你的判断。