إعدادات ضغط Gzip في Nginx لتقليص كل استجابة دون التأثير على السرعة

يُعدّ ضغط Gzip من أسرع المكاسب في تحسين أداء nginx. تعرّف على الإعدادات الدقيقة التي تُقلص HTML وCSS وJS بنسبة تصل إلى 80% دون زيادة الضغط على المعالج.

كل بايت يرسله خادمك يكلّف وقتاً. على اتصال سريع، لن تلاحظ فرقاً يُذكر. أما على شبكة الجوال، أو حين يعالج خادمك مئات الطلبات في آنٍ واحد، فإن هذه البايتات الإضافية تتراكم بسرعة. يُعدّ ضغط Gzip من أبسط التحسينات على مستوى الخادم، ويمنحك Nginx تحكماً دقيقاً في آلية عمله.

معظم تثبيتات Nginx الافتراضية تأتي مع Gzip إما معطلاً أو مُهيَّأً بالحد الأدنى. ضبطه بشكل صحيح لا يستغرق سوى 10 دقائق، والنتائج تظهر فوراً في أحجام الاستجابات وزمن الوصول للبايت الأول (Time to First Byte). لقد رأينا صفحات HTML تتقلص بنسبة 70-80%، وملفات JavaScript تنضغط إلى ثلث حجمها الأصلي بمجرد ضبط إعدادات Gzip بشكل صحيح.

كيف يعمل ضغط Gzip في Nginx فعلياً

عندما يرسل المتصفح طلباً، يُرسل معه ترويسة Accept-Encoding: gzip, deflate, br، وهذا يُخبر الخادم بأنه يستطيع التعامل مع الاستجابات المضغوطة. يفحص Nginx هذه الترويسة، وإذا كان Gzip مفعّلاً، يضغط جسم الاستجابة قبل إرسالها. يقوم المتصفح بفك الضغط بشكل تلقائي دون أي تغيير في كود تطبيقك.

المفاضلة الأساسية هنا هي بين وقت المعالج (CPU) وعرض النطاق الترددي. الضغط يستهلك قدراً صغيراً من طاقة المعالج على جانب الخادم. بالنسبة لمعظم المواقع، هذا قرار رابح - فالوفر في النطاق الترددي يفوق بكثير تكلفة المعالج، خاصة في الاستجابات النصية الكبيرة. الاستثناء هو الملفات المضغوطة أصلاً كصور JPEG وملفات ZIP ومقاطع MP4. محاولة ضغط هذه الملفات بـ Gzip تُهدر طاقة المعالج ولا تُقلص الحجم تقريباً.

كتلة إعداد Gzip الأساسية في Nginx

جميع إعدادات Gzip موجودة في ملف nginx.conf، عادةً في كتلة http لتطبيقها بشكل عام. إليك إعداداً قوياً للبداية:

http { gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_min_length 256; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/x-javascript application/xml application/xml+rss application/atom+xml image/svg+xml font/truetype font/opentype application/vnd.ms-fontobject; }

لنشرح التوجيهات التي تهم فعلاً.

gzip_comp_level: الإعداد الذي يُخطئ فيه كثيرون

مستوى الضغط يتراوح بين 1 (الأسرع، أقل ضغطاً) و9 (الأبطأ، أعلى ضغطاً). كثير من الأدلة توصي بضبطه على 9. لا تفعل ذلك.

المستوى 9 يستهلك طاقة معالج أعلى بكثير من المستوى 6، لكن الفرق في الحجم ضئيل - في الغالب أقل من 2-3% مقارنة بالمستوى 6. المستوى 6 هو النقطة المثالية. تحصل على ضغط بنسبة 70-80% لملفات HTML وCSS النموذجية دون إثقال كاهل المعالج على كل طلب. تحسين أداء nginx غالباً ما يتعلق بإزالة نقاط الاختناق لا بمطاردة مكاسب هامشية، وهذا مثال جيد على ذلك.

gzip_min_length: لا تضغط الاستجابات الصغيرة جداً

ضغط استجابة بحجم 50 بايت لا معنى له. إضافة ترويسة Gzip وحدها تُضيف نحو 20 بايت، فلن توفر شيئاً يُذكر وستكون قد استهلكت طاقة المعالج بلا فائدة. ضبط gzip_min_length 256 يُخبر Nginx بضغط الاستجابات الأكبر من 256 بايت فقط. لاستجابات API الصغيرة جداً أو الملفات النصية القصيرة، يوفر هذا التوجيه وقت معالجة حقيقياً.

gzip_vary: ضروري لطبقات التخزين المؤقت

فعّل دائماً gzip_vary on. هذا يُضيف ترويسة Vary: Accept-Encoding للاستجابات، مما يُخبر شبكات CDN وخوادم البروكسي بتخزين نسخ منفصلة من كل مورد - واحدة مضغوطة وأخرى غير مضغوطة. بدون هذا، قد يخزن CDN النسخة المضغوطة ويُقدمها لمتصفح أخبر بأنه لا يدعم Gzip، فيتلقى ذلك المتصفح بيانات غير مقروءة.

gzip_proxied: التعامل مع الطلبات عبر البروكسي

إذا كان Nginx خلف موازن حمل أو CDN، تصل الطلبات بترويسة Via. بشكل افتراضي، لن يضغط Nginx الاستجابات للطلبات الواردة عبر بروكسي. ضبط gzip_proxied any يجعله يضغط بغض النظر عن ذلك. في معظم الإعدادات هذا هو ما تريده.

أنواع MIME التي تُضغط وتلك التي تتجاوزها

التوجيه gzip_types يتحكم في أنواع المحتوى التي تُضغط. يضغط Nginx دائماً text/html بصرف النظر عن هذه القائمة، أما كل شيء آخر فيجب تحديده صراحةً.

اضغط هذه الأنواع من الملفات - فهي في معظمها نصية وتنضغط بشكل ممتاز:

  • ملفات CSS وJavaScript (غالباً أصغر بنسبة 60-80%)
  • استجابات JSON من API (غالباً أصغر بنسبة 70-85%)
  • صور SVG (غالباً أصغر بنسبة 50-70%)
  • خلاصات XML وخرائط الموقع
  • ملفات الخطوط ذات الصيغ النصية

تجاوز هذه الأنواع كلياً:

  • صور JPEG وPNG وWebP وAVIF - مضغوطة أصلاً
  • صيغ MP4 وWebM وغيرها من صيغ الفيديو
  • ملفات ZIP وGZ وغيرها من ملفات الضغط
  • ملفات PDF
  • ملفات خطوط WOFF2 - مضغوطة داخلياً

محاولة ضغط ملف JPEG بـ Gzip لا تفشل فحسب في توفير المساحة، بل قد تجعل الملف أكبر قليلاً مع استهلاك طاقة المعالج. اترك الصيغ الثنائية كما هي.

اختبار إعداد Gzip

بعد إعادة تحميل Nginx، تحقق من عمل الضغط باستخدام curl:

curl -H "Accept-Encoding: gzip" -I https://yourdomain.com

يجب أن ترى Content-Encoding: gzip في ترويسات الاستجابة. إن لم تجدها، تحقق من أن كتلة الإعداد موجودة في السياق الصحيح (كتلة http، لا داخل كتلة location حيث قد يتم تجاوزها).

للحصول على صورة أكثر شمولاً، اختبر رابطك عبر Google PageSpeed Insights أو تحقق من تبويب Network في أدوات مطور Chrome. انظر إلى عمود الحجم - سترى الحجم المنقول مقابل الحجم الفعلي. ملف CSS حجمه 80 كيلوبايت غير مضغوط يظهر بحجم 18 كيلوبايت منقولاً يعني أن Gzip يعمل بشكل صحيح.

المضي أبعد مع Gzip Static

إذا أردت دفع تحسين أداء nginx إلى مستوى أعلى، انظر إلى ngx_http_gzip_static_module. بدلاً من ضغط الملفات عند كل طلب، تضغطها مسبقاً وتخزن نسخ .gz على القرص. يُقدم Nginx الملف المضغوط مسبقاً مباشرةً حين يدعم العميل Gzip، متجاوزاً خطوة الضغط كلياً.

location ~* \.(js|css|html|xml|json|svg)$ { gzip_static on; expires max; add_header Cache-Control public; }

يعمل هذا النهج بشكل جيد في مسارات الأصول الثابتة التي تُبنى وتُنشر. تُنشئ عملية البناء app.js وapp.js.gz، ويُقدم Nginx الأنسب منهما. صفر تكلفة معالج وقت التشغيل للضغط على هذه الملفات. لقد تناولنا بالفعل موضوع إعداد عمليات الـ worker في كيفية إعداد عمليات Nginx Worker لأقصى إنتاجية، ويندمج Gzip الثابت بشكل طبيعي في نفس طبقة الأداء.

Gzip وBrotli: هل تستخدمهما معاً؟

Brotli هو خوارزمية ضغط أحدث من Google تحقق في الغالب ضغطاً أفضل بنسبة 15-25% من Gzip على الملفات النصية، مع تكلفة مشابهة على المعالج. جميع المتصفحات الحديثة تدعمه. إذا كانت وحدة ngx_brotli متاحة لديك، فإن تفعيلها جانب Gzip يمنحك أفضل ما في الأمرين - Brotli للمتصفحات الحديثة، وGzip كخيار احتياطي للمتصفحات القديمة.

نمط الإعداد مشابه لـ Gzip:

brotli on; brotli_comp_level 6; brotli_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;

يُرسل Nginx ضغط Brotli حين يطلبه المتصفح، ويرجع إلى Gzip في غير ذلك. لا عمل إضافي من جانبك بعد الإعداد.

ما تتوقعه بعد تفعيل Gzip

المكاسب حقيقية وفورية. صفحة نموذجية تحتوي على 200 كيلوبايت من HTML وCSS وJS غير مضغوطة تُنقل في الغالب بحجم 50-70 كيلوبايت بعد Gzip. هذا تقليص بنسبة 65-75% في حجم النقل. على اتصال جوال بطيء بسرعة 5 ميغابت في الثانية، هذا هو الفرق بين نقل يستغرق 320 ميلي ثانية وآخر يستغرق 90 ميلي ثانية - قبل احتساب DNS ومصافحات TCP أو التصيير.

TTFB (زمن الوصول للبايت الأول) لا يتغير بسبب Gzip وحده، إذ يقيس وقت معالجة الخادم قبل بدء تدفق الاستجابة. لكن وقت تحميل الصفحة الإجمالي ينخفض بشكل ملحوظ لأن جسم الاستجابة يصل بسرعة أكبر. إذا كنت تعمل على تحسين TTFB بشكل منفصل، فإن لماذا يُكلفك زمن الوصول للبايت الأول تحويلات يشرح ذلك بالتفصيل.

اجمع Gzip مع التخزين المؤقت على جانب الخادم وستكون قد ضاعفت اثنتين من أكثر تحسينات الخادم تأثيراً. استجابة مخزنة مؤقتاً ومضغوطة هي أسرع ما يمكن لخادمك تقديمه. للاطلاع على صورة أشمل لما يُشكّل خادماً سريعاً، تناول كيف يبدو الاستضافة السريعة فعلاً من الداخل الصورة الكاملة.

الإعداد أعلاه يستغرق دقائق للتطبيق. أعد تحميل Nginx، تحقق باستخدام curl، وانتهى الأمر. تحسين الأداء يبقى دائماً دون الحاجة إلى صيانة مستمرة.