المدونة

gPdf مقابل DocRaptor: لماذا يتفوق العرض على الحافة على HTML-to-PDF

يستخدم DocRaptor محرك Prince لتحويل HTML إلى PDF على backend مستضاف. يعرض gPdf JSON المنظم مباشرة على حافة Cloudflare. فرق السعر 18×، وهذا ليس عرضًا مؤقتًا.

DocRaptor منتج كفء. إنه يغلّف Prince، وهو محرك HTML-to-PDF ذي المعيار الذهبي، داخل REST API مستضافة مع retries وasync jobs ووثائق جيدة. موجود منذ أكثر من عقد، وبالنسبة إلى فرق كثيرة هو الخيار الواضح عندما لا تريد تشغيل Prince بنفسك.

gPdf أداة من نوع مختلف. لا يقبل HTML أصلًا؛ يأخذ JSON منظمًا ويعرض PDF مباشرة عند حافة Cloudflare. فرق السعر المعلن عند 100K صفحة شهريًا هو 5 دولارات/شهر (gPdf Basic) مقابل 89 دولارًا/شهر (DocRaptor Basic)، أي نحو 18×. هذا الفرق ليس promo افتتاحيًا. إنه بنيوي. يشرح هذا المقال لماذا تنتج البنية هذا السعر، وأين يناسب كل منتج فعليًا.

المعماريتان جنبًا إلى جنب

الطبقةDocRaptor (HTML → PDF)gPdf (JSON → PDF)
InputHTML + CSS، مع امتدادات Prince للوسائط المطبوعةJSON DocumentRequest
RendererPrince، محرك C++ مترجممحرك Rust مخصص، مترجم إلى WebAssembly
Hostingخوادم DocRaptor المركزية في منطقة datacenter أمريكيةCloudflare Workers في كل CF colo، أكثر من 300 مدينة
Cold startserver-side worker poolتشغيل V8 isolate خلال single-digit ms
Compute لكل renderlayout pass على HTML/CSS ثم pagination في Princedirect typesetting بلا layout interpretation pass
p50 لكل renderنحو 250-800 ms wall-clock، network + renderنحو 3-8 ms، network + render
Output determinismعالٍ، لأن Prince ناضجbyte-identical، أي same JSON → same bytes

إذا قرأت العمودين بوصفهما “طابعة HTML عامة” مقابل “عارض مستندات مخصص”، فقد فهمت القرار المعماري. كل شيء آخر، من latency إلى cost وحتى feature lists، يتبع هذا الاختيار.

ضريبة Prince

Prince جيد. لكنه يقوم أيضًا بعمل لا تحتاجه معظم workflows الخاصة بالفواتير والإيصالات والملصقات: تنفيذ CSS Paged Media، مثل page-break rules وrunning headers وfootnotes وcross-references وgenerated content boxes، لأي HTML عشوائي يرسله المستخدم.

هذه العمومية لها تكلفة runtime. لكي يقسم engine مستند HTML عشوائيًا إلى صفحات، عليه أن:

  1. يقرأ HTML ويتحقق منه
  2. يقرأ CSS cascade ويحلها، ربما مع امتدادات Prince الخاصة
  3. يبني render tree
  4. يشغل multi-pass layout، خصوصًا للجداول الممتدة عبر صفحات أو الأعمدة المتوازنة
  5. يحل cross-references عبر الصفحات
  6. يخرج PDF objects

معظم هذه passes هي تكلفة قبول HTML كمدخلات. إذا كان input لديك structured data أصلًا، كما يحدث غالبًا لأن invoice موجود كـ JSON object قبل تحويله إلى HTML، فأنت تدفع مقابل هذه passes في compute وlatency في كل render، وهي لا تضيف قيمة إلى output.

يتجاوز gPdf خطوة layout interpretation بالكامل. JSON DocumentRequest يحدد page layout هيكليًا من البداية، مثل { pages: [{ size, elements: [...] }] }. يصف renderer العناصر، ويقسم tables/lists إلى صفحات بصورة deterministic، ثم يخرج PDF. لا CSS cascade لحله، ولا float layout لحسابه، ولا cross-reference resolution pass.

النتيجة: نفس invoice الصفحة الواحدة التي تستغرق نحو 300 ms في DocRaptor تستغرق نحو 3 ms في gPdf. نحن لسنا أسرع لأننا كتبنا Prince أسرع؛ نحن أسرع لأننا لا نفعل معظم ما يفعله Prince.

”رخيص جدًا ليكون حقيقيًا” اعتراض شراء حقيقي

نحتاج إلى مواجهة هذا مباشرة لأنه يظهر في كل مكالمة B2B تقريبًا.

“5 دولارات/شهر لـ 100K renders. DocRaptor يكلّف 89 دولارًا. Anvil يكلّف 0.10 دولار لكل PDF، أي 10,000 دولار للحجم نفسه. ما الخطأ لديكم؟”

هناك ثلاثة أسباب صريحة تجعل هذا السعر ممكنًا:

1. لا نشغل browser

DocRaptor يوزع تكلفة بنية Prince على العملاء. gPdf يوزع تكلفة Cloudflare Worker واحد، وهي تقريبًا 0.50 دولار لكل مليون requests على Workers Bundled. مع input على شكل JSON، يستغرق renderer لدينا نحو 1.5 ms CPU لكل render. حتى مع margin بنسبة 50% تبقى في نطاق cents لكل ألف renders. الحساب نفسه هو السعر.

2. لا نشغل control plane

لا توجد async jobs، ولا callbacks، ولا retry queue، ولا document storage، ولا preview-link UI، ولا multi-tenant database. كل render هو round-trip واحد إلى stateless function والعودة. هذا يزيل سطح ops كاملًا تقوم معظم شركات “PDF API” بتسعيره، وهو أيضًا السطح الذي يبرر أسعارها.

3. النموذج يفلتر تلقائيًا workloads التي قد نخسر فيها

إذا كان مستندك يحتاج فعلًا إلى HTML-to-PDF، مثل عقد قانوني من 60 صفحة أو تقرير CSS Grid معقد، فستصطدم بنموذج JSON في الساعة الأولى وتذهب إلى DocRaptor. لا نحتاج إلى تسعير دفاعي لهذه workloads لأنها self-route. علينا فقط تسعير الذيل الطويل والضيق من workloads الخاصة بتحويل structured data إلى documents، حيث cost per render صغير فعلًا.

بجمع هذه الأسباب: 5 دولارات لكل 100K ليست loss leader، بل تكلفة البضاعة المباعة الفعلية مضافًا إليها margin. يمكننا إبقاءها كذلك لأن compute الأساسي رخيص إلى هذا الحد عندما لا تشحن browser.

متى يكون DocRaptor الخيار الصحيح

نحاول ألا نكتب مقارنات تخدمنا فقط. الحالات التي يفوز فيها DocRaptor فعلًا:

  • Input لديك HTML لا تتحكم فيه بالكامل. تقارير ينتجها المستخدمون، third-party templates، أو Markdown من CMS تم تحويله إلى HTML. لا تريد كتابة JSON mapper لمدخلات عشوائية.
  • تحتاج features من CSS Paged Media يدعمها Prince. Running headers/footers لكل chapter، complex footnote reflow، named-page selectors، generated tables of contents، indexes. لدى gPdf equivalents منظمة للجزء المشترك، لكن إذا كنت تعيش داخل @page :left selectors، فـ Prince صديقك.
  • لديك content team يكتب HTML/CSS، لا JSON. لا تفرض JSON authoring workflow على فريق غير هندسي. سيكرهون ذلك.
  • Async + callbacks + document storage كخدمة. يخزن DocRaptor ملفات PDF الناتجة ويعطيك signed URLs للتسليم. gPdf stateless تمامًا؛ الكود لديك يخزن النتيجة.

إذا كنت في أي من هذه الحالات، ابق على DocRaptor. إنه الأداة الصحيحة.

متى يكون gPdf الخيار الصحيح

الصورة المعاكسة:

  • Inputs لديك هي structured data أصلًا، مثل database rows أو JSON API payloads أو queue messages.
  • Latency مهم، مثل interactive checkout flows أو real-time label printing أو on-demand statement generation.
  • تهتم بـ byte-identical reproducibility للاختبارات أو audit trails أو e-invoice retention.
  • أنت حساس للتكلفة عند أي volume فوق بضعة آلاف renders شهريًا.
  • تحتاج barcodes مثل GS1-128 وQR وData Matrix وPDF417 وAztec وMaxiCode بدقة sub-millimetre. يدعم Prince تقنيًا SVG barcodes، لكن جعلها دقيقة حتى 0.1 mm عبر HTML/CSS ليس trivial.
  • تحتاج PDF/A (1b/2b/3b/4) أو Factur-X / ZUGFeRD attachments للامتثال.
  • لا تريد تشغيل JSON-to-HTML-to-PDF pipeline عندما يمكنك تشغيل JSON-to-PDF pipeline.

الهجرة ميكانيكية، لا استراتيجية

القلق الشائع هو: “الانتقال يعني إعادة كتابة كل templates”. غالبًا لا. معظم HTML-to-PDF templates هي 20% layout، والذي يصبح JSON structure مرة واحدة، و80% data interpolation، وهو نفسه تمامًا أيًا كان renderer.

المسار العملي:

  1. اختر نوع مستند واحدًا للهجرة. ابدأ بالأعلى volume، فهو أكبر توفير وأصغر blast radius.
  2. خذ data interface الخاص بـ HTML template، أي المتغيرات التي يدرجها، واكتب function صغيرة باسم mapToDocumentRequest(data).
  3. كرر العمل داخل Playground حتى يطابق output المطلوب.
  4. نفذ A/B في production: وجّه 5% من traffic إلى gPdf لمدة أسبوعين. قارن PDFs وقارن الفواتير.
  5. تقدم أو تراجع بناءً على data، لا على الانطباع.

رأينا فرقًا تنجز هذا في sprint واحد وتخفض 90% من فاتورة PDF في الشهر التالي. ورأينا فرقًا أخرى تكتشف أن workload لديها هو فعلًا حالة HTML-to-PDF وتبقى على DocRaptor، وهذا أيضًا قرار صحيح.

TL;DR

DocRaptorgPdf
Best atHTML → PDF لمحتوى عشوائيJSON → PDF لمستندات منظمة
Price (100K pages/mo)$89$5
p50 render250-800 ms3-8 ms
Edge-deployedلا، مركزينعم، أكثر من 300 Cloudflare colos
Async + storageنعم، includedلا، stateless by design
PDF/A + Factur-Xعبر Prince extensionsbuilt-in

إذا كانت مستنداتك structured data متنكرة في HTML من أجل renderer، فأنت تدفع مقابل translation step لا يحتاج إلى الوجود. جرّب Playground: صِف invoice واحدًا بـ JSON، اعرضه في browser خلال أقل من 5 ms، وانظر هل تطابق الفجوة إحساسك.