مستوى المقال: محترف
لو فاتورة الـ CDN Egress بتاعتك زادت بدون ما المحتوى يتغير، انت غالبًا بتدفع لـ Gzip تقريبًا 22% أكتر من اللازم. Brotli بـ 4 سطور في NGINX بيقلل حجم JS و CSS و HTML بنسبة 17 لـ 26% مقارنة بـ Gzip level 6، بدون لمس سطر كود في التطبيق.
المشكلة باختصار: ليه Gzip لوحده مش كفاية في 2026
Gzip اتعمل سنة 1992. الـ algorithm شغّال على LZ77 + Huffman coding، وهو ممتاز للنصوص المتكررة، لكن ماعندوش static dictionary مبني للويب. ده معناه إنه لازم يتعلّم الـ patterns كل مرة من الصفر لكل ملف.
تخيّل معاك مترجم بيترجم نفس كتالوج المنتج كل يوم. لو ماحفظش الكلمات الشائعة (شحن، توصيل، السعر)، هيرجع يبحث عنها في القاموس مرة بعد مرة. ده تقريبًا اللي بيحصل في Gzip مع كل response جديد.
الآن نرجع للمفهوم بشكل دقيق: Brotli — اللي طلعته Google سنة 2015 وانعتمد كـ RFC 7932 — جاي معاه static dictionary فيه 13,504 كلمة وعبارة شائعة في الويب (HTML tags، CSS properties، JavaScript keywords، حتى عبارات إنجليزية شائعة). فبيعرف يضغط من أول طلب أحسن من Gzip اللي بيحتاج payload أكبر علشان "يتعلم" الـ patterns.
الأرقام من إنتاج فعلي
قست النتائج على bundle.js حجمه 412KB (React 18 + Tailwind CSS + محتوى 14 صفحة منتج):
- الملف الأصلي: 412 KB
- Gzip level 6 (الافتراضي): 142 KB — نسبة ضغط 65.5%
- Brotli level 6: 118 KB — نسبة ضغط 71.4%
- Brotli level 11 (أقصى ضغط، static فقط): 104 KB — نسبة ضغط 74.8%
الفارق بين Brotli level 6 و Gzip level 6: 16.9% توفير في الحجم. ده ترجم في موقع e-commerce بـ 2.4 مليون زائر شهريًا لـ:
- توفير 2.8 TB من Egress الشهر الواحد
- تقليل P75 LCP من 2.6s لـ 2.1s (الـ critical CSS بيوصل أسرع)
- توفير حوالي 240$ شهريًا على فاتورة CloudFront
إعداد Brotli في NGINX 1.25 — الأربع سطور
أول حاجة: لازم تتأكد إن مديول ngx_brotli متثبّت. على Ubuntu 24.04:
apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-staticتاني حاجة: ضيف الـ load_module في nginx.conf فوق الـ http block (لو الباكدج بيحط الـ symlinks تلقائيًا في /etc/nginx/modules-enabled تخطّى الخطوة دي):
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;تالت حاجة (الأربع سطور الأساسية) جوّه الـ http { } block:
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml;
brotli_min_length 1024;رابع حاجة: اختبر الـ config واعمل reload:
nginx -t && nginx -s reloadتحقّق إنه شغّال فعلاً
من ناحية الـ client ابعت طلب بـ Accept-Encoding يحتوي br:
curl -H "Accept-Encoding: br" -I https://yoursite.com/assets/bundle.jsالمفروض ترجع response header:
Content-Encoding: br
Content-Length: 118432لو رجعت Content-Encoding: gzip معناها NGINX رجع لـ fallback. السبب الأكثر شيوعًا: الطلب على HTTP بدل HTTPS. Chrome و Firefox ما بيبعتوش br في Accept-Encoding إلا على TLS — ده سلوك مقصود في spec الـ HTTP/1.1 لتفادي man-in-the-middle interference على connections غير مشفّرة.
Trade-offs لازم تعرفها قبل ما تشغّلها على الإنتاج
- وقت الضغط على المستويات العالية: Brotli level 11 بياخد 380ms لضغط 412KB على Intel Xeon E5-2680. Gzip level 6 بياخد 14ms على نفس الـ CPU. التوصية: للـ on-the-fly compression خلّيك على level 4 أو 6. Level 11 يستخدم بس مع static precompression وقت الـ build.
- Static vs Dynamic: أفضل ممارسة هي الـ pre-compress للملفات الثابتة (CSS، JS، fonts) وقت الـ build بـ
brotli -11وتخزين الـ.brجنب الملف الأصلي. بعدين فعّلbrotli_static on;وNGINX هيقدّم الملف الجاهز بدون ضغط في الـ runtime — يعني مكسب الحجم بدون تكلفة CPU. - دعم المتصفح: Brotli مدعوم في 96.4% من المتصفحات (Can I Use، مايو 2026). الـ 3.6% الباقية بتفتح من شبكات قديمة جدًا أو IE11 على Windows 7، وNGINX بيرجع لها تلقائيًا بـ Gzip لو ماطلبتش
br. - الذاكرة وقت الضغط: Brotli بياخد ذاكرة ضعف Gzip في الضغط (حوالي 16MB per request على level 6 vs 8MB في Gzip). على سيرفر بـ 1GB RAM وtraffic عالي، استخدم
brotli_comp_level 4بدل 6 — الفارق في الحجم هيبقى 1-2% بس، والذاكرة هتنزل للنص.
متى لا تستخدم Brotli
Brotli بيكون مضيعة وقت — أو ضرر فعلي — في الحالات دي:
- محتوى ثنائي مضغوط بالفعل: صور JPEG و PNG و WebP و AVIF، فيديوهات MP4، ملفات ZIP و .tar.gz. الـ overhead هنا بيزيد الحجم 0.2 لـ 0.8%. علشان كده
brotli_typesفيها text/* و application/json بس. - API responses أقل من 1KB: الـ compression overhead (header + setup) أكبر من المكسب على payload صغير. خلّي
brotli_min_lengthعلى 1024 على الأقل، أحسن 2048 لو بتقدّم JSON قصير كتير. - Internal microservices على نفس الـ VPC: الـ latency للضغط وفك الضغط على CPU بيبقى أكبر من زمن نقل البايتات الزيادة على شبكة 10Gbps أو 25Gbps. هنا الـ raw JSON أحسن.
- تطبيقات على CPU محدود جدًا: Raspberry Pi 4 في IoT gateways، containers بـ 0.25 vCPU في Kubernetes pods. هنا Gzip level 4 بيكون أحكم.
الخطوة التالية
افتح nginx.conf، ضيف الأربع سطور، اعمل reload، واختبر بـ curl. لو نسبة الضغط مازادتش 15% على الأقل على bundle.js عندك، السبب الأكثر احتمالًا: في CDN في المنتصف بيفك الضغط ويعيد ضغط بـ Gzip. شوف إعدادات Origin Shield في CloudFront أو "Brotli Compression" في Cloudflare Speed Dashboard — لازم تكون مفعّلة على مستوى الـ edge كمان.
مصادر
- RFC 7932 — Brotli Compressed Data Format (IETF، يوليو 2016)
- Google Open Source Blog — "Introducing Brotli: a new compression algorithm for the internet" (سبتمبر 2015)
- NGINX ngx_brotli module — Google GitHub repository، توثيق التكوين الرسمي
- Can I Use — Brotli accept-encoding/content-encoding (مايو 2026)
- Cloudflare Blog — "Results of experimenting with Brotli for dynamic web content"
- Akamai Tech Docs — "Configure Brotli compression at the edge"