شغّل NextPDF على منصّات بلا خادم
لمحة سريعة
قسم بعنوان «لمحة سريعة»محرّك نواة NextPDF الأصلي العامل داخل العملية حِملٌ شبه مثالي للبيئات بلا خادم.
فهو PHP خالصة تعمل داخل عمليتك — composer require nextpdf/core،
تبني مستندًا، تأخذ البايتات. لا ثنائيّ خارجي يُولَّد، ولا متصفّح بلا واجهة، ولا
عفريت يبقى حيًّا، ولا مقبس إلى خدمة مساعِدة جانبية. فدالّةٌ تبني ملف PDF تبدأ
باردةً، وتشغّل PHP لديك، وتُرجِع البايتات، وتخرج. وهذا يتطابق نظيفًا مع
AWS Lambda (عبر بيئة تشغيل Bref)، وGoogle Cloud Run، وAWS App Runner.
تغطّي هذه الصفحة نشر ذلك المحرّك الأصلي على بيئات التشغيل الثلاث تلك ومجموعةً صغيرة من القيود الحقيقية التي تفرضها:
- نظام ملفّات بيئة التشغيل غير دائم: لا يضمن Lambda إلّا
/tmpقابلًا للكتابة، بينما لبيئات تشغيل الحاويات (Cloud Run، App Runner) نظام ملفّات زائلٌ محصورٌ بالحاوية — وفي الحالتين يجب أن تسافر الخطوط داخل حزمة النشر أو الصورة وأن تُسجَّل في PHP (لا يقرأ المحرّك أيّ متغيّر بيئة لمسار الخطوط)؛ - يدفع البدء البارد ثمن التحميل التلقائي وأيّ تسخينٍ للخطوط، فسخّن
FontRegistryمرّةً لكلّ حاوية، لا لكلّ استدعاء؛ - يجب قياس حجم الحزمة والذاكرة والمهلة بحسب البناء، لا بحسب طلبٍ تافه.
هذه الصفحة فقط للمحرّك الأصلي. أمّا جسر Chrome
(writeHtmlChrome عبر حزمة nextpdf/artisan المقترحة) فقصّةٌ مختلفة وأثقل: إذ
يستدعي Chromium بلا واجهة عبر symfony/process، وهو ما لا يحتويه ملف zip
عاديٌّ لـLambda أو حاويةٌ نحيلة. وتشغيل Chromium على Lambda يعني طبقةً مخصّصةً
بالمتصفّح ومكتباته المشتركة، وحُزمًا أكبر بكثير، وبدءًا باردًا أطول بكثير — خارج
نطاق هذه الصفحة. والمحرّك المجرّد لا يحتاج أيًّا من ذلك.
قبل أن تبدأ، أكّد أن هذه العناصر في مكانها:
- لتطبيقك ملفّا
composer.jsonوcomposer.lockمُودَعان، معnextpdf/coreبوصفه تبعية. - لديك ملفات الخطوط التي تنوي تضمينها، وأنت مرخّص لتضمينها.
- لديك سلسلة الأدوات لهدفك — واجهة Bref وإطار
serverlessلـLambda، أو بناء حاوية لـCloud Run / App Runner.
لماذا يلائم المحرّك الأصلي البيئات بلا خادم
قسم بعنوان «لماذا يلائم المحرّك الأصلي البيئات بلا خادم»بقراءته مباشرةً من الحزمة، يتطلّب nextpdf/core php: >=8.4 <9.0 ومجموعةً
صغيرة من امتدادات PHP — ext-mbstring وext-intl وext-gd
وext-openssl وext-zlib وext-curl. وتجمّع طبقات PHP القياسية لـBref كلًّا
منها. وتوفّر صور حاويات php:8.4 الرسمية openssl وcurl وzlib جاهزة، لكنّ
mbstring وgd وintl غير مجمَّعة — فهي تتطلّب تثبيت تبعيات النظام وتمكين
الامتدادات بـdocker-php-ext-install (انظر
دليل النشر بـDocker).
على Bref لا شيء غريب يُترجَم؛ وعلى مسار الحاوية تُمكِّن تلك الامتدادات الثلاثة في
بناء الصورة للمحرّك المجرّد.
ما يجعل الملاءمة نظيفة هو ما لا يفعله المحرّك:
- لا عملية فرعية لمسار النواة. فبناء مستندٍ واستدعاء
getPdfData()PHP داخل العملية من طرفٍ إلى طرف. وتوجد تبعيةsymfony/processلجسر Chrome الاختياري، لا للعرض الأصلي — فإنتاج PDF الأصلي لا يُولِّد عمليةً أبدًا. - لا حالة دائمة. فكلّ استدعاءٍ يبني مستندًا جديدًا ويُرجِع بايتات. لا شيء يجب أن يبقى بين الطلبات إلّا الحاوية الدافئة، التي تستغلّها لتسخين الخطوط (أدناه) لكن لا تعتمد عليها أبدًا للصحّة.
- لا حاجة إلى دليل عملٍ قابل للكتابة. فالمحرّك يبني ملف PDF في الذاكرة
ويُرجِعه سلسلةً؛ ولا يمسّ القرص إلّا إذا استدعيتَ أنت
save(). وعلى البيئات بلا خادم لا تفعل — بل تُرجِع البايتات — فلا يَعَضّ غيابُ نظام ملفّاتٍ دائمٍ مسارَ البناء أبدًا.
القيد الصعب الوحيد: لا نظام ملفّات دائم قابل للكتابة
قسم بعنوان «القيد الصعب الوحيد: لا نظام ملفّات دائم قابل للكتابة»نظام ملفّات النشر غير دائم، لكنّ النموذج يختلف بحسب بيئة التشغيل.
لا يضمن AWS Lambda إلّا /tmp قابلًا للكتابة (512 ميغابايت افتراضيًّا،
قابلٌ للضبط حتى 10 غيغابايت)؛ وبقية نظام ملفّات الدالّة للقراءة فقط. ولبيئات تشغيل
الحاويات (Cloud Run، App Runner) نظام ملفّاتٍ قابلٌ للكتابة زائلٌ محصورٌ
بالحاوية بدلًا من نموذج /tmp فقط — لكنّ أيّ شيءٍ يُكتب هناك يُفقَد عند إعادة
تدوير الحاوية، فهو مساحة عملٍ مؤقّتة لا تخزين. وفي كلّ حالة، فضّل /tmp أو وحدة
تخزينٍ مضبوطة للتجهيز، ولا تعتمد أبدًا على الكتابة إلى مسار صورة التطبيق بوصفه تخزينًا
دائمًا. ويترتّب على ذلك نتيجتان.
لا تستدعِ save() أبدًا متوقّعًا إخراجًا دائمًا. يكشف NextPDF\Core\Document
عن كلٍّ من save(string $path): void وgetPdfData(): string. وعلى البيئات بلا
خادم تستخدم getPdfData() وتُرجِع البايتات أو ترفعها — لا تعامل الكتابة إلى دليل
التطبيق بوصفها تخزينًا دائمًا. وإن لزمك تجهيز ملفّ (مثلًا، لرفعه متعدّد الأجزاء إلى
تخزين الكائنات)، فاكتب تحت /tmp (أو وحدة تخزينٍ مضبوطة) ونظّف، مع تذكّر أنّ هذه
المساحة المؤقّتة تبقى على حاويةٍ دافئة عبر الاستدعاءات وتُحتسَب على حدّ حجمها.
use NextPDF\Core\Document;
// Right for serverless: get the bytes, return or upload them.$pdf = $document->getPdfData(); // string of PDF bytes, built in memory
// Avoid on serverless: save() writes to disk. On Lambda the application// directory is read-only; on Cloud Run / App Runner it is writable but// ephemeral (lost on container recycle). Neither is durable storage.// $document->save('/var/task/out.pdf'); // not durable — return the bytes insteadلا تثبّت خطوط نظام التشغيل وقت التشغيل، ولا تعتمد على الاكتشاف التلقائي للخطوط؛
جمّع ملفات خطوطك للإنتاج. فعلى Lambda يحجب نظام الملفّات للقراءة فقط
apt-get install fonts-* صراحةً؛ وعلى بيئة تشغيل حاوية أيّ تثبيتٍ وقت التشغيل
يَحُلّ على نظام ملفّاتٍ زائلٍ ويُفقَد عند إعادة التدوير التالية. ولن ينفع ذلك أصلًا،
لأنّ المحرّك الأصلي لا يقرأ خطوط نظام التشغيل / fontconfig — فهو يحلّ الخطوط من
ملفّاتٍ تسجّلها فقط. فللإنتاج يجب أن تُشحَن ملفات الخطوط داخل أثر النشر. وإن جلبتَ
عمدًا ملفات خطوطٍ إلى /tmp أو وحدة تخزينٍ مضبوطة، فعليك تسجيلها صراحةً في سجلّ
الخطوط وقبول كلفة البدء البارد والموثوقية المضافة — وهو ليس نمط إنتاجٍ مُوصًى به.
جمّع الخطوط وسجّلها في الحزمة أو الصورة
قسم بعنوان «جمّع الخطوط وسجّلها في الحزمة أو الصورة»يحلّ المحرّك الأصلي الخطوط من ملفات الخطوط عبر
NextPDF\Typography\FontRegistry، لا من fontconfig أو خطوطٍ مثبَّتةٍ في نظام
التشغيل. وعلى البيئات بلا خادم هذا غير قابلٍ للتفاوض: فلا نظام ملفّاتٍ دائمٍ لوضع
الخطوط بعد النشر، فهي تُشحَن داخل الحزمة (ملف zip أو طبقةٌ لـLambda) أو داخل
الصورة (Cloud Run / App Runner).
جمّع ملفّاتك .ttf / .otf / .ttc تحت دليلٍ في مشروعك —
resources/fonts/ هو الاصطلاح — كي تُدرَج في الأثر. ثمّ سجّل ذلك الدليل في PHP.
لا يقرأ المحرّك أيّ متغيّر بيئةٍ لمسار الخطوط: فـNEXTPDF_FONTS_PATH هو القيمة
الافتراضية لمفتاح إعداد fonts_path لحزمة nextpdf/laravel
(env('NEXTPDF_FONTS_PATH', resource_path('fonts'))) ولا يستهلكه إلّا ذلك
التكامل مع الإطار، لا nextpdf/core. ويجب على دالّةٍ مجرّدة أن تبني السجلّ بالدليل
المجمَّع:
use NextPDF\Typography\FontRegistry;use NextPDF\Core\DocumentFactory;use NextPDF\Graphics\ImageRegistry;
// Register the directory the deployment artifact bundled the fonts into.// On Lambda/Bref the code root is /var/task; adjust for your runtime.$registry = new FontRegistry(__DIR__ . '/resources/fonts');// (equivalently, $registry->addFontDirectory(__DIR__ . '/resources/fonts');)
$factory = new DocumentFactory($registry, new ImageRegistry(maxCacheBytes: 0));$document = $factory->create();هذا كلّ ما يخصّ البيئات بلا خادم للخطوط. أمّا قواعد تسمية الملفات، وواجهة السجلّ الكاملة، والتعامل مع نظام الملفّات غير الدائم فتعيش في الصفحة المخصّصة — لا تكرّرها هنا. اقرأ وفّر الخطوط للمحرّك الأصلي في الإنتاج للنمط الكامل، وسجّل الدليل نفسه الذي جمّعت. ويغطّي دليل النشر بـDocker التجميع المكافئ من جانب الصورة لحالة Cloud Run / App Runner.
البدء البارد: سخّن FontRegistry مرّةً لكلّ حاوية
قسم بعنوان «البدء البارد: سخّن FontRegistry مرّةً لكلّ حاوية»يدفع البدء البارد ثمن تمهيد PHP، ومحمِّل Composer التلقائي المُحسَّن، وأيّ تحليلٍ للخطوط يطلقه أوّل بناء. لا يمكنك تجنّب التمهيد، لكن يمكنك نقل عمل الخطوط خارج المسار الساخن وإعادة استخدامه عبر الاستدعاءات الدافئة.
ابنِ FontRegistry وDocumentFactory مرّةً واحدة، خارج المُعالِج، كي يعيشا
طوال عمر الحاوية ويُعاد استخدامهما في كلّ استدعاءٍ دافئ. واختياريًّا استدعِ
warmup() بملفات الخطوط التي تعلم أنّك ستستخدمها، كي تُحلَّل أثناء التهيئة بدلًا
من العرض الأوّل، ثمّ lock() السجلّ كي تُجمَّد حالته المُحلَّلة ولا يتسابق أيّ
تغييرٍ لكلّ استدعاء:
use NextPDF\Typography\FontRegistry;use NextPDF\Core\DocumentFactory;use NextPDF\Graphics\ImageRegistry;
// Container-scoped, built once at cold start (module scope, not per request).$fontsDir = __DIR__ . '/resources/fonts';$registry = new FontRegistry($fontsDir);
// Parse the fonts you will actually use now, so the first render does not.$registry->warmup([ $fontsDir . '/liberation/LiberationSans-Regular.ttf', $fontsDir . '/liberation/LiberationSans-Bold.ttf',]);
// Freeze the parsed state for the life of the warm container.$registry->lock();
$factory = new DocumentFactory($registry, new ImageRegistry(maxCacheBytes: 0));
// Each invocation: fresh document from the shared, warm factory.$handler = static function (array $event) use ($factory): string { $document = $factory->create(); $document->addPage(); $document->cell(0, 10, 'Hello from serverless', newLine: true);
return $document->getPdfData();};استدعِ warmup() قبل lock() — فالسجلّ يُجمَّد بمجرّد قفله، فتسخينٌ بعد ذلك
يثير خطأ إعداد. وعامِل خطًّا يفشل تحميله عند التسخين بوصفه خطأ وقت نشرٍ، لا
تفصيلًا وقت تشغيل: تحقّق من أنّ كلّ مسار خطٍّ تنوي تسخينه موجودٌ فعلًا ويُحلَّل عند
البدء، وأفشِل النشر (أو فحص صحّتك) إن لم يكن، بدلًا من ترك مسارٍ مكتوبٍ بخطأٍ مطبعيٍّ
يظهر لاحقًا محارفَ ناقصة. وأبقِ قائمة التسخين على الخطوط التي يحتاجها استدعاءٌ
نموذجي؛ فتسخين عائلةٍ كبيرة نادرًا ما تستخدمها لا يطيل إلّا كلّ بدءٍ بارد.
دالّة Bref على AWS Lambda
قسم بعنوان «دالّة Bref على AWS Lambda»يوفّر Bref بيئة تشغيل PHP لـLambda بوصفها طبقةً منشورة
وإضافة serverless.yml. وتشحن بيئة التشغيل php-84 بالفعل الامتدادات التي
يحتاجها nextpdf/core، فتنشر شيفرتك وخطوطك وتوجّه دالّةً إلى مُعالِج. أبسط
serverless.yml:
service: nextpdf-serverless
provider: name: aws region: us-east-1 runtime: provided.al2023
plugins: - ./vendor/bref/bref
functions: generate: handler: handler.php description: Generate a PDF with the native NextPDF engine runtime: php-84 memorySize: 1024 # size to the build; see "Sizing" below timeout: 30 # seconds; raise for large documents # The Lambda filesystem is read-only except /tmp. Fonts ship in the # package under resources/fonts and are registered in the handler.يبني المُعالِج المستند بالمصنع الدافئ المحصور بالحاوية ويُرجِع البايتات. ولواجهة
HTTP API، أرجِعها مرمَّزةً بـbase64 بنوع المحتوى application/pdf كي يعامل
API Gateway الجسمَ بوصفه ثنائيًّا؛ ولمشغّل استدعاءٍ أو طابور، ارفع البايتات إلى
تخزين الكائنات وأرجِع المفتاح:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\FontRegistry;
// --- Cold-start: built once per container, reused across warm invocations. ---$fontsDir = __DIR__ . '/resources/fonts';$registry = new FontRegistry($fontsDir);$registry->warmup([$fontsDir . '/liberation/LiberationSans-Regular.ttf']);$registry->lock();$factory = new DocumentFactory($registry, new ImageRegistry(maxCacheBytes: 0));
// --- Per-invocation handler. ---return static function (array $event) use ($factory): array { $document = $factory->create(); $document->addPage(); $document->cell(0, 10, 'Invoice', newLine: true);
// getPdfData() materializes the whole PDF in memory and returns it. $bytes = $document->getPdfData();
return [ 'statusCode' => 200, 'isBase64Encoded' => true, 'headers' => ['Content-Type' => 'application/pdf'], 'body' => base64_encode($bytes), ];};تحقّق من أنّ الحزمة تحتوي بيئةً سليمة قبل أن توصّل إليها حركة المرور. تشحن
nextpdf/core واجهة سطر أوامر مثبَّتة عند vendor/bin/nextpdf يُبلِّغ أمرها
doctor عن الامتدادات التي يحتاجها المحرّك بالضبط. شغّله مرّةً على صورة بيئة
التشغيل أو الطبقة نفسها لتأكيد وجود PHP 8.4 وكلّ امتدادٍ مطلوب.
Cloud Run و App Runner
قسم بعنوان «Cloud Run و App Runner»يشغّل Cloud Run وApp Runner حاويةً بدلًا من دالّةٍ مضغوطة، فالبناء صورة
Docker من
احتوِ تطبيق NextPDF في حاوية،
لا حزمة Bref. وقيود المحرّك الأصلي متطابقة: جمّع الخطوط في الصورة، وسجّل الدليل
المجمَّع في PHP، وشغّل بلا امتيازات، وعامِل نظام الملفّات بوصفه غير دائم. وبخلاف
نموذج /tmp فقط في Lambda، لحاوية Cloud Run / App Runner نظام ملفّاتٍ قابلٌ
للكتابة زائلٌ محصورٌ بالحاوية — لكنّه يُعاد ضبطه عند كلّ إعادة تدوير، فاستخدم
/tmp (نظام tmpfs على Cloud Run) أو وحدة تخزينٍ مضبوطة للمؤقّت ولا تعتمد أبدًا
على الكتابة إلى مسار صورة التطبيق بوصفه تخزينًا دائمًا.
الفروق عن Lambda تشغيليّةٌ، لا بنيويّة:
- يمكن للحاوية أن تبقى دافئةً عبر الطلبات تحت إعداد تزامن، فيؤتي تسخين
FontRegistry/DocumentFactoryالمحصور بالحاوية أعلاه ثماره عبر طلباتٍ كثيرة، لا الاستدعاء التالي فحسب. - تخدم عبر HTTP (واجهة
FPMأو خادم PHP المدمج) بدلًا من حدث استدعاء، فتُرجِع البايتات عبر استجابة إطارك. ولمستندٍ كبير، أرجِعها استجابةً متدفّقة — انظر دفّق ملف PDF كبيرًا مولَّدًا بوصفه استجابة HTTP. - تُضبَط مهلة الطلب والذاكرة على الخدمة (مهلة/ذاكرة خدمة Cloud Run؛ إعداد نسخة App Runner) بدلًا من لكلّ دالّة.
وكلّ ما عدا ذلك — مجموعة الامتدادات، وتسجيل الخطوط، واستدعاء إخراج getPdfData()
— هو الشيفرة نفسها كمُعالِج Lambda.
القياس: الحزمة والذاكرة والمهلة
قسم بعنوان «القياس: الحزمة والذاكرة والمهلة»- حجم الحزمة والصورة. يحمل الأثر
vendor/(للإنتاج فقط — ثبّت بـ--no-dev) وخطوطك المجمَّعة. وتهيمن الخطوط: فعائلة CJK كاملة عشرات الميغابايت. اشحن فقط الخطوط التي تعرضها فعلًا لإبقاء حزمة Lambda تحت حدودها والصورة صغيرة، وهو ما يقصّر البدء البارد أيضًا. وعائلة Liberation المجمَّعة (resources/fonts/liberation/) صغيرةٌ وتغطّي استبدال Helvetica المتوافق متريًّا. - الذاكرة. يبني
getPdfData()المستند كاملًا في الذاكرة ويُرجِعه سلسلةً واحدة، فذروة الذاكرة تقارب حجم ملف PDF منتهٍ واحد زائد مجموعة عمل البناء. قِس ذاكرة الدالّة/الحاوية بحسب أكبر مستندٍ تولّده، لا بحسب متوسّط. وعلى Lambda، تقيس الذاكرة أيضًا وحدة المعالجة، فالذاكرة الأكبر تعني غالبًا بناءً أسرع وتشغيلًا أرخص رغم السعر الأعلى لكلّ مللي ثانية — قِس كليهما. مستندٌ من بضع صفحاتٍ مريحٌ عند 512–1024 ميغابايت؛ والمستندات الثقيلة بالصور أو الكثيرة الصفحات تحتاج أكثر. - المهلة. يهيمن البناء، لا النقل، على ميزانية الطلب. اضبط مهلة الدالّة فوق أسوأ زمن بناءٍ مع هامش. وإن كان مستندٌ كبيرًا بما يكفي للمخاطرة بمهلة، فانقل التوليد إلى مشغّلٍ لا تزامني (دالّة Lambda مدعومة بطابور أو مهمّة Cloud Run) تكتب النتيجة إلى تخزين الكائنات بدلًا من حجب طلبٍ متزامن.
- حجم
/tmp. إن جهّزت أيّ شيءٍ تحت/tmp، فاحسب حدّ حجمه وتذكّر أنّه يبقى عبر الاستدعاءات الدافئة — نظّف، وإلّا فحاويةٌ طويلة العمر تملؤه ببطء.
الحالات الحدّية والمزالق
قسم بعنوان «الحالات الحدّية والمزالق»- لا
save()دائم إلى دليل التطبيق. نظام ملفّات النشر غير دائم — دليل تطبيق Lambda للقراءة فقط (/tmpوحده يقبل الكتابة)، ونظام ملفّات حاوية Cloud Run / App Runner قابلٌ للكتابة لكنّه زائل. استخدمgetPdfData()وأرجِع/ارفع البايتات؛ وجهّز تحت/tmpأو وحدة تخزينٍ مضبوطة إن لزم. - لا تعتمد على الاكتشاف التلقائي للخطوط. لا تثبّت خطوط نظام التشغيل وقت
التشغيل، ولا تعتمد على الاكتشاف التلقائي للخطوط؛ جمّع ملفات خطوطك للإنتاج. لا
يقرأ المحرّك الأصلي خطوط نظام التشغيل /
fontconfig— فهو يحلّ فقط الملفّات التي تسجّلها. وإن جلبتَ عمدًا ملفات خطوطٍ إلى/tmpأو وحدة تخزينٍ مضبوطة، فعليك تسجيلها صراحةً في سجلّ الخطوط وقبول كلفة البدء البارد والموثوقية المضافة. جمّع الملفّات وسجّلها. انظر صفحة الخطوط المرتبطة أعلاه. NEXTPDF_FONTS_PATHلا يفعل شيئًا للمحرّك المجرّد. فهو الافتراضي لإعداد nextpdf/laravel، لا متغيّرٌ يقرأهnextpdf/core. ومُعالِج Bref مجرّدٌ يضبط ذلك المتغيّر وحده لا يسجّل خطوطًا ويعرض مربّعات بديلة.- جسر Chrome لا يلائم دالّةً عادية. يحتاج
writeHtmlChromeإلى Chromium بلا واجهة ومسار العملية الفرعيةsymfony/process. ووضع Chromium على Lambda يتطلّب طبقةً مخصّصةً بالمتصفّح ومكتباته، وحُزمًا أكبر بكثير، وبدءًا باردًا طويلًا. والمحرّك الأصلي وwriteHtmlلا يحتاجان أيًّا من ذلك — فضّلهما على البيئات بلا خادم. - كلفة البدء البارد هي التحميل التلقائي زائد تحليل الخطوط. استخدم
--optimize-autoloaderعلى تثبيت الإنتاج وسخّن السجلّ مرّةً لكلّ حاوية. لا تسخّن خطوطًا نادرًا ما تستخدمها. - يحتاج API Gateway إلى معالجةٍ ثنائية. أرجِع
isBase64Encoded: trueمع Content-Type: application/pdf، واضبط الواجهة لتعاملapplication/pdfبوصفه نوع وسائط ثنائيًّا، وإلّا تلقّى العميل بايتات تالفة. - النسخة المميَّزة وionCube شأن أثرٍ أثقل. تحتاج بُنى NextPDF Pro / Enterprise المرمَّزة بـionCube إلى مُحمِّل ionCube المطابق لبناء PHP بالضبط في بيئة التشغيل، وهو ما لا تتضمّنه طبقة Bref الجاهزة. وذلك خارج نطاق نشرٍ نواةٍ بلا خادم.
ملاحظات أمنية
قسم بعنوان «ملاحظات أمنية»- لا تشحن تبعيات تطوير. ثبّت بـ
--no-devكي لا تدخل أدوات الاختبار والتحليل حزمة الدالّة أو الصورة أبدًا. - تحقّق من المدخلات قبل البناء. بناء PDF مدفوعٌ بمدخلات الطلب ناقلُ استنزافٍ للذاكرة؛ ارفض المدخلات الخارجة عن النطاق أو المفرطة الحجم عند الحدّ قبل أيّ عمل بناء، وقيّد التزامن كي لا تضاعف الحركة العالية ذروة الذاكرة إلى فشل نفاد ذاكرة.
- أبقِ الخطوط والتراخيص خارج الآثار العامة. جمّع فقط الخطوط المرخّص لك بتضمينها، ولا تخبز أبدًا ملفّ ترخيصٍ مميَّز في صورةٍ أو طبقةٍ مدفوعةٍ علنًا — بل وفّره وقت التشغيل عبر قيمة بيئةٍ أو مدير أسرار.
- أقلّ امتياز. امنح الدالّة/الخدمة فقط أذونات IAM التي تحتاجها (مثلًا، إذن الكتابة إلى دلو الإخراج الواحد)، وشغّل الحاوية بلا امتيازات كما يبيّن دليل Docker.
المطابقة
قسم بعنوان «المطابقة»لا يدّعي هذا الدليل أيّ ادّعاءٍ معياريّ. حقائق المنصّة مقروءةٌ مباشرةً من حزمة
nextpdf/core: القيد php: >=8.4 <9.0 والامتدادات المطلوبة ext-mbstring
وext-intl وext-gd وext-openssl وext-zlib وext-curl. وتجمّع طبقة بيئة
تشغيل Bref القياسية لـPHP-8.4 الستّة كلّها؛ وتوفّر صورة php:8.4 الرسمية
openssl وcurl وzlib، لكن يجب تثبيت mbstring وgd وintl وتمكينها في بناء
الصورة بـdocker-php-ext-install (انظر صفحة Docker). واستدعاء الإخراج هو سطح
النواة الحقيقي
NextPDF\Core\Document::getPdfData(): string (وقرينه على القرص
save(string $path): void). وتُسجَّل الخطوط عبر
NextPDF\Typography\FontRegistry — وسيطة دليله المُنشِئة /
addFontDirectory()، مع warmup(array $fontFiles) وlock() لنمط البدء البارد —
موصَّلةً عبر NextPDF\Core\DocumentFactory::create().
وNEXTPDF_FONTS_PATH هو مفتاح إعداد fonts_path لحزمة nextpdf/laravel
(env('NEXTPDF_FONTS_PATH', resource_path('fonts')))، لا متغيّرٌ يقرأه
nextpdf/core. وأمر doctor لواجهة سطر أوامر nextpdf مُصرَّحٌ به بوصفه
"bin": ["bin/nextpdf"] في الحزمة ومثبَّتٌ عند vendor/bin/nextpdf في تطبيقٍ
مستهلِك. وأسماء بيئة تشغيل Bref وسلوكيات AWS Lambda / Cloud Run / App Runner
هي ميزات أولئك البائعين الموثَّقة.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- احتوِ تطبيق NextPDF في حاوية: صورة الإنتاج المستخدَمة لهدفَي Cloud Run / App Runner.
- وفّر الخطوط للمحرّك الأصلي في الإنتاج: تسمية ملفات الخطوط، وواجهة السجلّ، ونمط التسخين والقفل الذي تعتمد عليه هذه الصفحة.
- دفّق ملف PDF كبيرًا مولَّدًا بوصفه استجابة HTTP: نموذج الذاكرة لإرجاع مستندٍ مبنيٍّ عبر HTTP على Cloud Run / App Runner.
- اعرض عند الحافّة بـCloudflare: حين لا تكون دالّةٌ داخل العملية بيئة التشغيل الصحيحة.