مفاهیم پایه

فعال‌سازی Gzip و Brotli در Nginx؛ فشرده‌سازی درست برای بارگذاری سریع‌تر

تهیه: کلودیفای (نگارش با کمک هوش مصنوعی) · انتشار: · زمان مطالعه: ۷ دقیقه

https://example.comGzipBrotliNginxمفاهیم پایهفعال‌سازی Gzip و Brotli درNginx؛ فشرده‌سازی درستبرای بارگذاری سریع‌ترمجلهٔ کلودیفایclodify.net/blog
پاسخ کوتاه

فشرده‌سازی HTTP حجم فایل‌های متنی مثل HTML، CSS، جاوااسکریپت و JSON را پیش از ارسال به‌شدت کم می‌کند. Gzip در همهٔ نسخه‌های Nginx موجود است و کافی است با gzip on و فهرست gzip_types فعالش کنید. Brotli فشرده‌سازی بهتری دارد اما به ماژول جداگانه نیاز دارد. تصاویر و فایل‌های از پیش فشرده را دوباره فشرده نکنید، سطح فشرده‌سازی را متوسط نگه دارید و نتیجه را با هدر Content-Encoding در curl بررسی کنید.

فشرده‌سازی HTTP چیست؟

بیشتر محتوای یک وب‌سایت متن است: HTML صفحه، فایل‌های CSS، کتابخانه‌های جاوااسکریپت، پاسخ‌های JSON از API و آیکون‌های SVG. متن تکرار زیادی دارد؛ نام کلاس‌ها، تگ‌ها و کلمات کلیدی بارها تکرار می‌شوند. الگوریتم‌های فشرده‌سازی همین تکرارها را پیدا و خلاصه می‌کنند و حجم فایل‌های متنی معمولاً چند برابر کوچک‌تر می‌شود.

فرایند ساده است: مرورگر در درخواست خود با هدر Accept-Encoding اعلام می‌کند چه روش‌هایی را پشتیبانی می‌کند، مثلاً gzip, br. سرور پاسخ را با یکی از آن روش‌ها فشرده می‌کند و با هدر Content-Encoding اعلام می‌کند از کدام استفاده کرده است. مرورگر پاسخ را باز می‌کند و نمایش می‌دهد. کاربر هیچ تفاوتی جز سرعت بیشتر حس نمی‌کند.

مزیت فشرده‌سازی برای کاربران با اینترنت کند یا موبایل بیشتر است، و برای شما به معنای مصرف کمتر پهنای باند و ترافیک سرور است؛ موضوعی که در سرورهایی با محدودیت یا هزینهٔ ترافیک اهمیت دارد. تفاوت این دو مفهوم در مقالهٔ پهنای باند و ترافیک توضیح داده شده است.

مذاکرهٔ فشرده‌سازی
درخواستفشرده‌سازیمرورگرAccept-Encoding: br, gzipNginxانتخاب بهترین روشپاسخ فشردهContent-Encoding: brدرخواستفشرده‌سازیمرورگرAccept-Encoding: br, gzipNginxانتخاب بهترین روشپاسخ فشردهContent-Encoding: br
شکل ۱ مرورگر روش‌های پشتیبانی‌شده را اعلام می‌کند و سرور بهترین گزینهٔ مشترک را انتخاب می‌کند.

Gzip یا Brotli؟

Gzip قدیمی‌ترین و فراگیرترین روش است. همهٔ مرورگرها و همهٔ نسخه‌های Nginx آن را پشتیبانی می‌کنند و فعال کردنش فقط چند خط پیکربندی است.

Brotli را گوگل توسعه داده و برای محتوای وب بهینه شده است. در سطح فشرده‌سازی مشابه، معمولاً فایل‌های کوچک‌تری از Gzip تولید می‌کند، مخصوصاً برای HTML، CSS و جاوااسکریپت. همهٔ مرورگرهای مدرن آن را پشتیبانی می‌کنند، اما فقط روی اتصال HTTPS. عیب آن در Nginx این است که به ماژول جداگانه نیاز دارد.

راهبرد معقول: Gzip را همیشه فعال کنید چون پایه و جایگزین مطمئن است، و اگر امکانش هست Brotli را هم اضافه کنید. Nginx برای هر مرورگر بهترین روشی را که پشتیبانی می‌کند انتخاب می‌کند.

فعال‌سازی Gzip

در بیشتر توزیع‌ها، gzip on در فایل اصلی /etc/nginx/nginx.conf از قبل فعال است، اما فقط برای text/html. باید انواع دیگر را هم اضافه کنید. یک فایل جدا بسازید:

# /etc/nginx/conf.d/gzip.conf
gzip on;
gzip_vary on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_types
    text/plain text/css text/xml text/javascript
    application/javascript application/json application/xml
    application/rss+xml application/atom+xml
    image/svg+xml font/ttf font/otf;

اگر gzip on در nginx.conf هم هست، تکراری بودن آن خطای تست ایجاد می‌کند؛ در این صورت آن خط را از یکی از دو فایل حذف کنید. سپس:

sudo nginx -t && sudo systemctl reload nginx

توضیح هر دستور:

  • gzip_vary: هدر Vary: Accept-Encoding را اضافه می‌کند تا CDNها و کش‌ها نسخهٔ فشرده و غیرفشرده را جدا نگه دارند و نسخهٔ فشرده به مرورگری که پشتیبانی نمی‌کند داده نشود.
  • gzip_comp_level: سطح فشرده‌سازی از یک تا نه. سطح‌های بالا فقط کمی فایل را کوچک‌تر می‌کنند اما پردازنده را بسیار بیشتر مصرف می‌کنند. سطح متوسط بهترین تعادل است.
  • gzip_min_length: فایل‌های خیلی کوچک ارزش فشرده‌سازی ندارند.
  • gzip_proxied any: پاسخ‌هایی را که از پشت پروکسی یا CDN درخواست شده‌اند هم فشرده می‌کند.
  • gzip_types: فهرست نوع‌های محتوایی که باید فشرده شوند. text/html همیشه به‌طور پیش‌فرض فشرده می‌شود و نیازی به نوشتنش نیست.

ساختار فایل‌های پیکربندی Nginx در آموزش پیکربندی Nginx توضیح داده شده است.

Gzip یا Brotli
Gzip
  • پشتیبانی در همهٔ مرورگرها و ابزارها
  • در Nginx بدون ماژول اضافه
  • روی HTTP و HTTPS
  • جایگزین مطمئن و همیشگی
در برابر
Brotli
  • فشرده‌سازی بهتر برای متن وب
  • در Nginx به ماژول جدا نیاز دارد
  • در مرورگرها فقط روی HTTPS
  • گزینهٔ ارجح برای مرورگرهای مدرن
شکل ۲ هر دو را با هم فعال کنید؛ Nginx برای هر مرورگر بهترین گزینه را انتخاب می‌کند.

چه چیزی را فشرده نکنیم؟

تصاویر JPEG، PNG و WebP، ویدیوها، فایل‌های ZIP و فونت‌های WOFF2 خودشان از پیش فشرده‌اند. فشرده‌سازی دوباره تقریباً هیچ صرفه‌ای در حجم ندارد و فقط پردازنده را مشغول می‌کند؛ گاهی حتی فایل کمی بزرگ‌تر می‌شود. به همین دلیل این نوع‌ها در gzip_types نیامده‌اند. SVG استثناست، چون در واقع یک فایل متنی XML است و خوب فشرده می‌شود.

یک نکتهٔ امنیتی هم وجود دارد: در صفحه‌هایی که هم اطلاعات محرمانه مثل توکن‌های امنیتی و هم ورودی قابل‌کنترل توسط مهاجم را در یک پاسخ دارند، فشرده‌سازی در شرایط خاص می‌تواند به حملاتی مثل BREACH کمک کند. راه‌حل معمول در فریم‌ورک‌ها، تصادفی کردن توکن در هر پاسخ است و برای بیشتر سایت‌ها نیازی به غیرفعال کردن فشرده‌سازی نیست.

افزودن Brotli

در اوبونتوهای جدید، ماژول Brotli برای Nginx در مخازن رسمی موجود است:

sudo apt install -y libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static

اگر بسته برای نسخهٔ شما موجود نبود، باید ماژول را از سورس و هماهنگ با نسخهٔ دقیق Nginx کامپایل کنید که کار پیچیده‌تری است. پس از نصب، پیکربندی مشابه Gzip:

# /etc/nginx/conf.d/brotli.conf
brotli on;
brotli_comp_level 5;
brotli_min_length 256;
brotli_types
    text/plain text/css text/xml text/javascript
    application/javascript application/json application/xml
    image/svg+xml font/ttf font/otf;

دوباره با nginx -t تست و reload کنید.

فشرده‌سازی از پیش برای فایل‌های استاتیک

فشرده‌سازی در لحظه برای هر درخواست کمی پردازنده مصرف می‌کند. برای فایل‌های استاتیک که تغییر نمی‌کنند، می‌توانید نسخهٔ فشرده را یک بار هنگام ساخت پروژه تولید کنید؛ مثلاً app.js.gz و app.js.br کنار app.js. با دستورهای زیر Nginx به‌جای فشرده‌سازی دوباره، مستقیم همان فایل آماده را می‌فرستد:

gzip_static on;
brotli_static on;

در این حالت می‌توانید سطح فشرده‌سازی را در مرحلهٔ ساخت بالاترین مقدار بگذارید، چون فقط یک بار انجام می‌شود. بسیاری از ابزارهای ساخت فرانت‌اند افزونه‌ای برای تولید این فایل‌ها دارند.

فشرده‌سازی و CDN

اگر سایت پشت CDN است، بیشتر CDNها خودشان فشرده‌سازی را برای کاربر نهایی انجام می‌دهند و حتی ممکن است Brotli را بدون نیاز به ماژول روی سرور شما ارائه کنند. با این حال فعال بودن Gzip روی سرور اصلی همچنان مفید است، چون ترافیک بین سرور و CDN را هم کم می‌کند. مهم‌ترین نکته، وجود هدر Vary: Accept-Encoding است تا CDN نسخه‌های مختلف را درست از هم جدا کند. تنظیمات کش در راهنمای Cache-Control در CDN آمده است.

user@laptop: ~
$ curl -sI -H 'Accept-Encoding: br, gzip' https://example.com/ | grep -iE 'encoding|vary'content-encoding: brvary: Accept-Encoding$ curl -sI -H 'Accept-Encoding: gzip' https://example.com/ | grep -i encodingcontent-encoding: gzip$ 
شکل ۳ مرورگر مدرن Brotli می‌گیرد و کلاینتی که فقط Gzip می‌شناسد، نسخهٔ Gzip را.

اثر فشرده‌سازی روی سرعت واقعی سایت

فشرده‌سازی فقط یکی از عوامل سرعت است، اما از کم‌هزینه‌ترین‌هاست. مرورگر پیش از نمایش صفحه باید HTML و فایل‌های CSS اصلی را کامل دریافت کند؛ هرچه این فایل‌ها کوچک‌تر باشند، اولین نمایش صفحه زودتر اتفاق می‌افتد. این اثر روی اتصال‌های موبایل و شبکه‌های شلوغ که سرعت دانلود محدود است، بسیار محسوس‌تر از اینترنت پرسرعت است.

برای اینکه تصویر کامل داشته باشید، فشرده‌سازی را کنار چند بهینه‌سازی دیگر ببینید: کش درست فایل‌های استاتیک در مرورگر، استفاده از CDN برای نزدیک کردن محتوا به کاربر، و کوچک کردن تصاویر. هر کدام بخشی از مسیر را کوتاه می‌کنند. مفهوم CDN و اثر آن در مقالهٔ CDN چیست آمده است.

اگر پس از فعال کردن فشرده‌سازی مصرف پردازنده به‌طور محسوسی بالا رفت، که در سطح‌های متوسط بعید است، ابتدا سطح فشرده‌سازی را پایین بیاورید و سپس فشرده‌سازی از پیش را برای فایل‌های استاتیک فعال کنید. روش پیدا کردن عامل مصرف CPU در رفع مصرف بالای CPU آمده است.

تست فشرده‌سازی

با curl و هدر Accept-Encoding درخواست بفرستید و هدر Content-Encoding پاسخ را ببینید:

curl -sI -H "Accept-Encoding: br, gzip" https://example.com/ | grep -i -E "content-encoding|vary"
curl -sI -H "Accept-Encoding: gzip" https://example.com/assets/app.css | grep -i content-encoding

اگر content-encoding: br یا gzip دیدید، فشرده‌سازی کار می‌کند. در مرورگر هم می‌توانید در ابزار توسعه‌دهنده و تب Network، ستون حجم انتقال‌یافته را با حجم واقعی فایل مقایسه کنید. اگر فشرده نمی‌شود، بررسی کنید نوع محتوای پاسخ در gzip_types باشد؛ گاهی برنامه نوع محتوای غیرمعمولی می‌فرستد که در فهرست نیست.

سؤالات متداول

آیا فشرده‌سازی بار CPU سرور را زیاد می‌کند؟

در سطح‌های متوسط، افزایش مصرف پردازنده بسیار کم است و صرفه‌جویی در زمان انتقال آن را جبران می‌کند. فقط سطح‌های بالا را برای فشرده‌سازی در لحظه استفاده نکنید و برای فایل‌های استاتیک از فشرده‌سازی از پیش بهره بگیرید.

Brotli را فعال کنم یا Gzip کافی است؟

Gzip به‌تنهایی بیشتر سود فشرده‌سازی را می‌دهد. Brotli کمی بهتر است و اگر بستهٔ آن به‌راحتی نصب می‌شود ارزشش را دارد؛ اما اگر سایت پشت CDN است، احتمالاً CDN خودش Brotli را به کاربران ارائه می‌کند.

چرا فایل‌های JSON پاسخ API فشرده نمی‌شوند؟

احتمالاً application/json در gzip_types نیست یا پاسخ از پشت پروکسی می‌آید و gzip_proxied تنظیم نشده است. همچنین اگر برنامه خودش پاسخ را فشرده کرده باشد، Nginx دوباره فشرده نمی‌کند.

آیا تصاویر را هم باید Gzip کنم؟

خیر. JPEG، PNG و WebP از پیش فشرده‌اند و Gzip روی آن‌ها تقریباً اثری ندارد. برای کوچک کردن تصاویر، آن‌ها را با فرمت مناسب مثل WebP و ابعاد درست ذخیره کنید؛ SVG تنها استثنای قابل‌فشرده‌سازی است.

آماده‌اید؟ سرورتان را بسازید.

از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی

سرورتان را همین حالا بسازید.

ساعتی بپردازید. هر وقت خواستید حذف کنید.