Brotli และ Gzip: บีบอัดไฟล์บน Nginx ให้เว็บโหลดเร็วขึ้น

เปิดการบีบอัด Brotli และ Gzip บน Nginx ให้ไฟล์ CSS, JavaScript และ JSON เล็กลงหลายเท่า ติดตั้งโมดูลตาม Distro ทดสอบด้วย curl และรู้ว่าไฟล์ไหนไม่ควรบีบอัด

โดย ทีมงาน THAI DATA CLOUD อัปเดต อ่าน 10 นาที

แชร์FacebookXLINELinkedIn
Brotli — Brotli และ Gzip: บีบอัดไฟล์บน Nginx ให้เว็บโหลดเร็วขึ้น
Brotli และ Gzip: บีบอัดไฟล์บน Nginx ให้เว็บโหลดเร็วขึ้น

คำตอบสั้น ๆ: เปิดการบีบอัด Brotli และ Gzip บน Nginx ให้ไฟล์ CSS, JavaScript และ JSON เล็กลงหลายเท่า ติดตั้งโมดูลตาม Distro ทดสอบด้วย curl และรู้ว่าไฟล์ไหนไม่ควรบีบอัด

คู่มือนี้อธิบาย Brotli ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย

Brotli คืออัลกอริทึมบีบอัดข้อมูลที่ Google พัฒนาสำหรับเว็บโดยเฉพาะ บีบไฟล์ข้อความอย่าง CSS, JavaScript และ JSON ได้เล็กกว่า Gzip อีกราว 15-20% ส่วน Gzip เป็นมาตรฐานเดิมที่ทุกเบราว์เซอร์และทุกเครื่องมือรองรับ การเปิดทั้งสองแบบบน Nginx ทำให้หน้าเว็บโหลดเร็วขึ้น ใช้แบนด์วิดท์น้อยลง และช่วยคะแนน Core Web Vitals โดยไม่ต้องแก้โค้ดเว็บเลย

หลายเซิร์ฟเวอร์เปิด gzip on ไว้แล้วแต่บีบอัดได้เฉพาะ HTML เพราะค่าเริ่มต้นของ Nginx ไม่รวม CSS และ JavaScript คู่มือนี้จะตั้ง Gzip ให้ครอบคลุมไฟล์ที่ควรบีบอัด ติดตั้งโมดูล Brotli ตามแต่ละ Distro ทดสอบผลด้วย curl และอธิบายว่าไฟล์ประเภทไหนไม่ควรบีบอัดซ้ำ

สิ่งที่ต้องเตรียม

  • เซิร์ฟเวอร์ที่ใช้ Nginx จากแพ็กเกจของระบบบน Ubuntu 22.04/24.04, Debian 12 หรือ AlmaLinux/Rocky Linux 9 และสิทธิ์ sudo (ดู ติดตั้ง LEMP บน Ubuntu)
  • เว็บที่เปิดผ่าน HTTPS แล้ว เพราะเบราว์เซอร์ขอ Brotli เฉพาะการเชื่อมต่อ HTTPS (ดู ติดตั้ง SSL ด้วย Certbot)
  • URL ของไฟล์ CSS หรือ JavaScript ขนาดใหญ่ในเว็บไว้ทดสอบ ตัวอย่างใช้ https://www.example.com/assets/app.css
ลำดับการเลือกบีบอัด Brotli หรือ Gzip ตั้งแต่เบราว์เซอร์ส่ง Accept-Encoding จน Nginx ตอบ Content-Encoding
Nginx เลือก br ก่อนถ้าเบราว์เซอร์รองรับ ถ้าไม่รองรับจะใช้ gzip และส่งไฟล์เดิมเป็นทางสุดท้าย

ขั้นตอนที่ 1: ตรวจสถานะการบีบอัดปัจจุบัน

ส่ง Header Accept-Encoding เหมือนเบราว์เซอร์ แล้วดูว่าเซิร์ฟเวอร์ตอบ Content-Encoding อะไรกลับมา ถ้าไม่มีบรรทัดนี้แปลว่าไฟล์ยังไม่ถูกบีบอัด จากนั้นดูว่ามีการตั้ง gzip ไว้ที่ไหนบ้าง

curl -s -o /dev/null -D - -H 'Accept-Encoding: br, gzip' https://www.example.com/assets/app.css | grep -iE 'content-(type|encoding)'
grep -rn gzip /etc/nginx/nginx.conf /etc/nginx/conf.d/

ขั้นตอนที่ 2: ตั้งค่า Gzip ให้ครอบคลุมไฟล์ข้อความ

บน Ubuntu และ Debian ไฟล์ /etc/nginx/nginx.conf มี gzip on; อยู่แล้ว ให้ใส่ # หน้าบรรทัดนั้นก่อน ไม่เช่นนั้น Nginx จะแจ้ง "gzip" directive is duplicate เมื่อเพิ่มไฟล์ใหม่ บน AlmaLinux/Rocky ไม่มีบรรทัดนี้ จากนั้นสร้าง /etc/nginx/conf.d/compression.conf

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
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;
  • gzip_types ไม่ต้องใส่ text/html เพราะถูกบีบอัดเสมออยู่แล้ว ใส่ซ้ำจะได้คำเตือน
  • gzip_vary on ส่ง Header Vary: Accept-Encoding ให้ CDN และ Proxy เก็บ Cache แยกตามการบีบอัด
  • gzip_proxied any บีบอัดแม้คำขอผ่าน CDN หรือ Proxy มา และ gzip_comp_level 5 คือจุดสมดุลระหว่างขนาดไฟล์กับ CPU ระดับ 9 ได้ไฟล์เล็กลงอีกนิดเดียวแต่ใช้ CPU มากขึ้นชัดเจน
ตารางประเภทไฟล์ที่ควรและไม่ควรบีบอัดด้วย Brotli หรือ Gzip บน Nginx พร้อมเหตุผล
บีบอัดเฉพาะไฟล์ข้อความ ไฟล์ที่บีบอัดมาแล้วในตัวไม่ต้องบีบซ้ำ

ขั้นตอนที่ 3: ติดตั้งโมดูล Brotli ตาม Distro

Nginx ไม่มี Brotli ในตัว ต้องเพิ่มโมดูล ngx_brotli ซึ่งแต่ละ Distro มีให้ต่างกัน

# Ubuntu 24.04 และ Debian 12
sudo apt update
sudo apt install -y libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static
ls /etc/nginx/modules-enabled/ | grep brotli

# AlmaLinux / Rocky Linux 9 (ใช้ Nginx จาก AppStream)
sudo dnf install -y epel-release
sudo dnf install -y nginx-mod-brotli
ls /usr/share/nginx/modules/ | grep brotli

แพ็กเกจจะเพิ่มคำสั่ง load_module ให้เอง ข้อควรรู้: Ubuntu 22.04 ไม่มีโมดูล Brotli ใน Repository ทางการ ให้ใช้ Gzip อย่างเดียวไปก่อน ซึ่งได้ผลส่วนใหญ่แล้ว หรืออัปเกรดเป็น 24.04 ตาม คู่มือ do-release-upgrade ส่วนบน AlmaLinux/Rocky ถ้าใช้ Nginx จาก nginx.org หรือเปิด Module Stream อื่น dnf อาจแจ้งว่า nginx(abi) ไม่ตรง เพราะโมดูลต้องคอมไพล์ให้ตรงกับรุ่นของ Nginx ทุกครั้ง

ขั้นตอนที่ 4: เปิดใช้ Brotli ในไฟล์ตั้งค่า

เพิ่มบรรทัดเหล่านี้ต่อท้าย compression.conf รายการประเภทไฟล์ใช้ชุดเดียวกับ Gzip เมื่อเบราว์เซอร์รองรับทั้งสองแบบ Nginx จะเลือก Brotli ก่อน

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 application/rss+xml application/atom+xml image/svg+xml;

ระดับ 5 เหมาะกับการบีบอัดสด (On-the-fly) ทุกคำขอ ส่วนระดับ 11 ซึ่งเล็กที่สุดใช้ CPU สูงมาก ควรใช้เฉพาะการบีบอัดล่วงหน้าในขั้นตอนที่ 6

ขั้นตอนที่ 5: ตรวจไฟล์ reload และวัดผล

sudo nginx -t
sudo systemctl reload nginx
U=https://www.example.com/assets/app.css
curl -s -o /dev/null -w 'none: %{size_download}\n' "$U"
curl -s -o /dev/null -w 'gzip: %{size_download}\n' -H 'Accept-Encoding: gzip' "$U"
curl -s -o /dev/null -w 'br:   %{size_download}\n' -H 'Accept-Encoding: br' "$U"

%{size_download} คือจำนวนไบต์ที่ส่งจริงทางเครือข่าย ตัวเลขของ br ควรเล็กที่สุด ตรวจในเบราว์เซอร์ได้ที่ DevTools แท็บ Network คลิกไฟล์แล้วดู Response Headers ว่ามี content-encoding: br

หน้าจอ curl วัดขนาดไฟล์ CSS เดียวกันแบบไม่บีบอัด แบบ Gzip และแบบ Brotli หลังตั้งค่า Nginx
ไฟล์ CSS 182 KB เหลือ 31 KB เมื่อใช้ gzip และ 25 KB เมื่อใช้ br

ขั้นตอนที่ 6: บีบอัดไฟล์ Static ล่วงหน้า (ไม่บังคับ)

สำหรับไฟล์ที่ไม่เปลี่ยนจนกว่าจะ Deploy ครั้งถัดไป เช่น CSS และ JavaScript ที่ Build แล้ว ให้สร้างไฟล์ .br และ .gz ไว้ข้างไฟล์จริงด้วยระดับสูงสุด แล้วเปิด brotli_static on; และ gzip_static on; ใน compression.conf Nginx จะส่งไฟล์ที่บีบไว้แล้วโดยไม่เสีย CPU ทุกคำขอ

sudo apt install -y brotli        # AlmaLinux / Rocky: sudo dnf install -y brotli
cd /var/www/example/assets
brotli -k -q 11 app.css
gzip -k -9 app.css

ต้องสร้างไฟล์ใหม่ทุกครั้งที่ Deploy ไม่เช่นนั้นผู้ใช้จะได้ไฟล์เวอร์ชันเก่าที่บีบไว้ ควรใส่คำสั่งนี้ในขั้นตอน Build ของ การ Deploy ด้วย Git

ปัญหาที่พบบ่อยเกี่ยวกับ Brotli และ Gzip

ทดสอบด้วย curl ได้ br แต่เบราว์เซอร์ยังได้ gzip เป็นเพราะอะไร?

เบราว์เซอร์ส่ง br ใน Accept-Encoding เฉพาะเมื่อเปิดเว็บผ่าน HTTPS ถ้าเปิดผ่าน HTTP จะได้ gzip เสมอ อีกกรณีคือมี CDN คั่นกลาง ซึ่งเลือกการบีบอัดฝั่งผู้ใช้เอง ให้ตรวจการตั้งค่าบน CDN ด้วย

ตั้ง gzip_types แล้ว แต่ไฟล์ JavaScript ยังไม่ถูกบีบอัด ต้องแก้อย่างไร?

ตรวจ Content-Type ที่เซิร์ฟเวอร์ตอบจริงจากคำสั่งในขั้นตอนที่ 1 ชื่อประเภทต้องตรงกับใน gzip_types ทุกตัวอักษร Nginx บางรุ่นส่งไฟล์ .js เป็น application/javascript บางรุ่นเป็น text/javascript รายการในคู่มือนี้จึงใส่ไว้ทั้งสองแบบ

ควรบีบอัดรูปภาพ วิดีโอ หรือฟอนต์ WOFF2 ด้วยหรือไม่?

ไม่ควร ไฟล์ JPEG, PNG, WebP, AVIF, MP4, ZIP, PDF และ WOFF2 ถูกบีบอัดมาแล้วในตัว บีบซ้ำแทบไม่เล็กลงแต่เสีย CPU ทุกคำขอ ยกเว้น SVG ซึ่งเป็นข้อความ XML บีบได้ดี การลดขนาดรูปให้ทำที่ตัวไฟล์ เช่น แปลงเป็น WebP

เปิด Brotli แล้ว CPU สูงขึ้นมาก แก้อย่างไร?

มักเกิดจากตั้ง brotli_comp_level สูงเกินไป ให้ลดเหลือ 4-5 และใช้การบีบอัดล่วงหน้าในขั้นตอนที่ 6 กับไฟล์ Static ขนาดใหญ่ ไม่ควรเปิดการบีบอัดกับ Response ที่ใหญ่หลายสิบ MB เช่น ไฟล์ Export

ถ้าต้องการให้ทีมช่วยปรับแต่ง Nginx และความเร็วเว็บบน Cloud Linux Server ติดต่อทีมงาน THAI DATA CLOUD อ่านคำสั่งทั้งหมดได้ที่ ngx_http_gzip_module และ ngx_brotli ของ Google

อ่านเพิ่มเติมเกี่ยวกับ Brotli

แชร์FacebookXLINELinkedIn

มีคำถามเรื่องบริการ? ติดต่อทีมงาน