المدونة

gPdf مقابل Puppeteer: متى يكون Chromium بحجم 800 MB إجابة خاطئة

يحوّل Puppeteer أي صفحة ويب إلى PDF، لكنك غالبًا تدفع ثمن متصفح headless لا تستخدم معظمه. مقارنة عملية للمهندسين الذين يختارون مكدس PDF في 2026.

إذا وصلت إلى هنا بعد البحث عن “Puppeteer PDF alternative”، فغالبًا سؤالك الحقيقي هو شيء من هذا النوع:

“لماذا تحتاج دالة serverless لدي إلى بداية باردة مدتها ثانيتان و900 MB من RAM فقط لطباعة فاتورة واحدة؟”

Puppeteer أداة ممتازة. لكنها أيضًا حل مبالغ فيه جدًا للمهمة التي تستخدمه كثير من الفرق من أجلها: تحويل بيانات منظمة إلى PDF يمكن توقعه. هذه مقارنة للفريق الذي يكاد يشحن Puppeteer إلى الإنتاج، ويتساءل بصمت إن كان هناك خيار أعقل.

سنغطي أين يستحق Puppeteer وزنه، وأين لا يستحقه، وكيف تبدو مصفوفة المفاضلات الفعلية في 2026.

ماذا تشحن فعليا مع Puppeteer

عند npm install puppeteer، تسحب تقريبًا 170 MB من Chromium قبل احتساب dependencies غير المباشرة. وقت التشغيل، يحتاج headless Chromium عادة 600-900 MB من الذاكرة المقيمة لتصيير صفحة واحدة، و1-2 ثانية من البداية الباردة لتشغيل المتصفح. كل تصيير يمر بالخطوات التالية:

  1. تشغيل عملية المتصفح أو إعادة استخدام تجمع.
  2. فتح تبويب جديد.
  3. الانتقال إلى HTML / URL.
  4. انتظار domcontentloaded، وغالبًا الخطوط والصور وweb components.
  5. تنفيذ page.pdf() الذي يمرر الصفحة المرسومة عبر محرك PDF في Chromium.
  6. إغلاق التبويب.

هذه ضريبة منصة الويب كاملة. تدفعها سواء كان المستند عقدًا قانونيًا من 90 صفحة مع رسوم SVG مدمجة، أو ملصق شحن من صفحة واحدة بخمسة أسطر نص.

إذا كان الإدخال لديك HTML حقيقيًا يحتاج CSS layout ومحتوى يعمل بـ JavaScript وweb fonts وبقية منصة الويب، فالضريبة عادلة. أما كل ما عدا ذلك — الفواتير والملصقات والإيصالات والتذاكر والكشوف والشهادات — فهو غالبًا حرق للمال.

أين يفوز Puppeteer

كن صريحا هنا قبل أي migration:

  • تصيير HTML/CSS أمين. إذا كان نظام التصميم يخرج HTML وتريد PDF مطابقًا لذلك HTML على مستوى البكسل، فـ Puppeteer لا يُهزم. إنه Chrome يطبع حرفيًا.
  • ميزات منصة الويب. SVG مع filters، وحالات CSS Grid الطرفية، وweb components، ومحتوى يُقيَّم بـ JavaScript، وiframes من أطراف ثالثة — كلها تعمل.
  • تصحيح بصري. تستطيع أخذ screenshot في منتصف التصيير، وفتح DevTools على headless mode، ورؤية ما يراه محرك التصيير بالضبط.
  • لا توجد خطوة ترجمة. إذا كان المحتوى صفحة ويب بالفعل، فلا mapping إلى schema. page.goto(url); await page.pdf() هي السلسلة كلها.

إذا كان اثنان من هذه البنود يصفان عبء عملك الحقيقي، لا تغيّر. Puppeteer هو الإجابة الصحيحة.

أين يخسر Puppeteer

في الحالات الأخرى تتراكم التكلفة بسرعة.

الذاكرة والبداية الباردة في serverless

Node 20 Lambda أو Cloudflare Container نموذجي يشغّل Puppeteer:

المقياس قيمة نموذجية
حجم صورة الحاوية 250-400 MB (Chromium + Node + الكود لديك)
زمن البداية الباردة 1.8 - 2.5 ثانية
RAM دافئة لكل تصيير 600 - 900 MB
التصييرات المتزامنة لكل instance بحجم 1 GB 1، وأحيانًا 2 إذا كانت الصفحات صغيرة جدًا

إذا كان نظام الفواتير يتعامل مع 100,000 تصيير شهريًا، فأنت تدفع طاقة تشغيل المتصفح في كل حاوية باردة، رغم أن صفرًا من هذه التصييرات يحتاج تنفيذ JavaScript.

فخ الخطوط داخل الحاويات

يأتي Chromium بمجموعة خطوط افتراضية، وغالبًا تنقصها CJK والسيريلية والديفاناغاري والعربية وذيل طويل من glyphs الخاصة بأنظمة كتابة معينة. في الإنتاج يبدو ذلك هكذا:

فاتورة Q3 2025 لمكتب Tokyo تطبع ▢▢▢▢ 2025年第3四半期. العميل يصعّد. الفريق يقضي sprint في تثبيت الخطوط داخل Dockerfile وضبط CSS fallback.

NotoSans CJK وحده يضيف نحو 50 MB إلى الصورة. مجموعة Noto fallback عالمية تضيف نحو 250 MB. أنت تدفع ثمن Chromium و“كاتدرائية خطوط“ كاملة فقط لطباعة فاتورة يابانية واحدة.

Determinism

تصييرات Puppeteer ليست متطابقة على مستوى البايت بين إصدارات Chromium. قد يغيّر تحديث patch بسيط kerning أو baseline الخط أو مواضع فواصل الصفحات. إذا كانت لديك مجموعة اختبارات تقارن ملفات PDF، كما ينبغي، فكل تحديث Chromium يصبح تنقيبًا صغيرًا: ما الذي تغير في التصيير، وهل كان مقصودًا؟

JavaScript وقت التصيير

حتى صفحة HTML “static” يجب تحليلها، وحساب تخطيطها، ورسمها، ثم serialise الناتج. عمليًا، هذا 80-400 ms لكل صفحة على عملية دافئة. معظمه تخطيط، لا رسم.

للمقارنة: خادم يعيد JSON مباشرة إلى محرك تصيير ثنائي يستغرق 3-8 ms للفاتورة نفسها.

أين يناسب gPdf

يقلب gPdf النموذج: بدل أن تصف المستند كـ HTML وتطلب من متصفح رسمه، تصفه كـ JSON منظم (DocumentRequest) ويصدر محرك تصيير مكتوب بـ Rust ومترجم إلى WebAssembly ملف PDF مباشرة. لا متصفح، لا DOM، ولا مرور تخطيط بـ JavaScript.

هذا يبدو مقيّدًا، وهو كذلك فعلًا لمشكلات HTML. لكنه مناسب جدًا لفئة الفواتير / الملصقات / الإيصالات / الكشوف / الشهادات:

  • بياناتك منظمة أصلًا. الفاتورة تعيش عادة ككائن { customer, lines, totals, taxes, notes }. لا تريد تحويلها أولًا إلى HTML، ثم جعل المتصفح يقرأ HTML مرة أخرى إلى تخطيط. تريد الانتقال مباشرة من البيانات إلى PDF.
  • التخطيط يصبح عقدًا. عندما تعني font_size: 11 دائمًا 11 نقطة، وتعني gap: 8 دائمًا 8 نقاط، يرى مهندسان يراجعان PR الإخراج نفسه. لا توجد فجوة تفسير display: flex.
  • الإخراج متطابق على مستوى البايت. نفس الإدخال → البايتات نفسها. تستطيع استخدام git diff على ملفين PDF ورؤية ما تغير فقط.
  • البداية الباردة هي بداية وقت التشغيل، لا إقلاع متصفح. يبدأ V8 isolate على Cloudflare Workers خلال 5-20 ms. تبقى وحدة WASM ساخنة في الذاكرة عبر الاستدعاءات على isolate نفسه.

تصيير gPdf نموذجي لفاتورة من صفحة واحدة يسجل 3-5 ms p50 wall-clock على Edge، من أقرب Cloudflare colo يصل إليه المستخدم. هذا أسرع بنحو رتبتين من حيث الحجم من المسار الدافئ في Puppeteer، وثلاث رتب من المسار البارد.

مصفوفة القرار

عبء العمل استخدم Puppeteer استخدم gPdf
تقرير HTML موجود → PDF ✅ الخيار الأول ⚠️ يحتاج إعادة كتابة
فواتير، كشوف، إيصالات ⚠️ مطرقة ثقيلة ✅ الخيار الأول
ملصقات شحن مع باركودات ❌ تجنبه (مشكلات خطوط) ✅ الخيار الأول
فاتورة إلكترونية (Factur-X / ZUGFeRD / EN 16931) ❌ لا دعم مدمج ✅ مدمج
أرشفة طويلة الأمد PDF/A ⚠️ تحتاج مرور Ghostscript ✅ ملفات تعريف مدمجة
نماذج نظام تصميم مطابقة للبكسل ✅ الخيار الأول ❌ الأداة الخطأ
رسوم بيانية تحتاج D3 / Recharts حقيقيًا ✅ الخيار الأول ❌ الأداة الخطأ
تذاكر، شهادات، بطاقات أسماء ⚠️ مبالغ فيه ✅ الخيار الأول
أي شيء يحتاج JavaScript وقت التصيير ✅ الخيار الوحيد ❌ الأداة الخطأ

إن كنت في العمود الأيمن في أكثر من ثلاث صفوف، فالتوفير واضح.

مقارنة حقيقية: فاتورة من صفحة واحدة

نفس المحتوى، نفس مقاس الورق، نفس الخطوط (NotoSans)، ونفس ملف تعريف PDF/A-3b:

Puppeteer (warm Lambda, 1 GB) gPdf (warm Cloudflare Worker)
p50 latency 180 ms 3.4 ms
p99 latency 420 ms 8 ms
عقوبة البداية الباردة +1800 ms لأول تصيير +12 ms لأول تصيير
الذاكرة عند الذروة 720 MB 18 MB
حجم الصورة / الوحدة 280 MB 4.5 MB
رموز CJK ❌ إلا إذا ثُبتت صراحة ✅ NotoSans CJK مدمج
التكلفة / 100K تصيير نحو $240 (حوسبة Lambda) نحو $5 (خطة gPdf Basic)

الصف الأخير يفاجئ الناس. الفارق حقيقي وبنيوي، لا سعر دعائي. نحن لا نحتاج إلى توزيع تكلفة إقلاع Chromium، أو ذاكرة المتصفح، أو بدايات الحاويات الباردة، لذلك تكون تكلفة وحدة التصيير صغيرة فعلًا.

“لكن $5/100,000 صفحة يبدو رخيصا جدا. ما الخدعة؟”

الخدعة هي بالضبط أننا لا نشحن متصفحًا. تكلفة تشغيل محرك تصيير ثنائي على V8 isolate دافئ هي مللي ثوانٍ من CPU وكيلوبايتات من الذاكرة. تسعيره بأسعار Puppeteer يعني فرض ثمن بنية تحتية لا نشغلها.

متى تختار Puppeteer رغم ذلك

الإجابة الصادقة ليست دائما “استخدم gPdf”:

  1. أنت تشغّل Puppeteer في الإنتاج وهو يعمل. لا تهاجر من أجل الرياضة. الوقت الصحيح لتقييم gPdf هو عندما يبدأ Puppeteer بإيلامك — غالبًا عندما تتجاوز فواتير الحوسبة الشهرية 400 دولار، أو عندما تكسر البداية الباردة SLA downstream.
  2. مستنداتك صفحات ويب موجودة، نقطة. تقرير من 60 صفحة يولده المستخدمون، مصمم بنظامك، مع رسوم متداخلة ومحتوى ديناميكي، ليس هجرة JSON. إنه إعادة تصميم.
  3. تحتاج تطابقًا تامًا مع معاينة ويب. بعض مسارات العمل، مثل “ما تراه في المحرر هو ما يُطبع”، تحتاج فعليًا إلى أن يكون Chromium هو محرك التصيير في المكانين.

إذا لم تنطبق هذه الحالات، فالحساب مباشر: نشر أصغر، زمن استجابة أقل، فاتورة أقل، إخراج مطابق على مستوى البايت، ولا دراما تثبيت خطوط.

كيف تهاجر workload حقيقي

إذا اقتنعت بما يكفي للتجربة، فالهجرة غالبًا spike من يوم إلى يومين لكل نوع مستند، وليست إعادة هندسة كاملة:

  1. اختر مستندًا واحدًا — ابدأ بالأعلى حجمًا، لا بالأكثر تعقيدًا.
  2. اربط أقسام قالب HTML المنطقية بعناصر gPdf JSON (text, box, table, barcode, image).
  3. استخدم Playground للتكرار على DocumentRequest حقيقي حتى يطابق الإخراج المطلوب.
  4. اربط شكل بياناتك الحالي بدالة mapper صغيرة تصدر JSON.
  5. شغّل المسار الجديد A/B أمام مسار Puppeteer لمدة أسبوع. قارن ملفات PDF. قرر بناءً على البيانات.

معظم الفرق تجد أن نموذج JSON يصبح منطقيًا خلال يوم. الصعب ليس الأداة الجديدة، بل تفكيك حركات HTML/CSS التي تراكمت في القالب القديم.

TL;DR

Puppeteer هو الإجابة الصحيحة لـ صفحات الويب. أما المستندات، فأنت تدفع ضريبة 100-200× على كل تصيير لتجنب تكلفة صغيرة لمرة واحدة: وصف المستند كبيانات. إذا كان أسطولك يصيّر فواتير أو ملصقات أو إيصالات أو كشوف أو تذاكر أو أي شيء آخر “بالشكل نفسه كل مرة، والقيم فقط تتغير”، فإن محرك تصيير edge-native مثل gPdf سيكون أسرع وأصغر وأرخص وأكثر حتمية بصورة قابلة للقياس.

جرّبه في Playground. إنه Worker حقيقي على Edge، بلا تسجيل، والاستجابة تصل إلى متصفحك خلال أقل من 5 ms.