คำตอบสั้น ๆ: ตั้งให้ Nginx ตอบไฟล์คงที่และหน้าเว็บที่ไม่เปลี่ยนบ่อยแทน PHP ลดภาระเซิร์ฟเวอร์ พร้อมกฎยกเว้นที่ต้องตั้งให้ครบ
คู่มือนี้อธิบาย Nginx Caching ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
โครงสร้างของ Plesk คือ Nginx อยู่หน้า Apache โดยค่าเริ่มต้น Nginx ทำหน้าที่เพียงส่งต่อคำขอทั้งหมดไปให้ Apache ซึ่งหมายความว่าแม้แต่การขอไฟล์รูปก็ต้องผ่านสองชั้น
การตั้งให้ Nginx จัดการไฟล์คงที่เองและแคชหน้าเว็บที่ไม่เปลี่ยนบ่อย ลดภาระได้มากโดยไม่ต้องแก้โค้ดเว็บเลย คู่มือนี้ตั้งค่าทั้งสองอย่างพร้อมกฎยกเว้นที่ห้ามลืม
สิ่งที่ต้องเตรียม (Nginx Caching)
- Plesk Obsidian และสิทธิ์ผู้ดูแลระบบ
- เว็บที่ทำงานอยู่แล้วและวัดความเร็วก่อนหน้าไว้
# วัดก่อน
for i in 1 2 3; do
curl -s -o /dev/null -w 'total=%{time_total}s ttfb=%{time_starttransfer}s\n' https://example.com/
done
ขั้นตอนที่ 1: เปิดให้ Nginx จัดการไฟล์คงที่ (Nginx Caching)
ไปที่ Domains แล้วเลือกโดเมน แล้ว Apache & nginx Settings
ติ๊ก Smart static files processing ซึ่งทำให้ Nginx ตอบไฟล์รูป CSS และ JavaScript เองโดยไม่ผ่าน Apache
ตั้งรายการนามสกุลไฟล์ในช่อง Serve static files directly by nginx
jpg jpeg gif png webp avif svg ico css js woff woff2 ttf eot mp4 webm pdf zip
ผลที่ได้ชัดเจนมากสำหรับเว็บที่มีรูปเยอะ เพราะแต่ละหน้าอาจมีคำขอไฟล์คงที่หลายสิบรายการ
ขั้นตอนที่ 2: เพิ่ม header สำหรับแคชฝั่งเบราว์เซอร์ (Nginx Caching)
ในช่อง Additional nginx directives ของโดเมนนั้น
location ~* \.(jpg|jpeg|png|gif|webp|avif|svg|ico)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
location ~* \.(css|js)$ {
expires 30d;
add_header Cache-Control "public";
access_log off;
}
location ~* \.(woff|woff2|ttf|eot)$ {
expires 365d;
add_header Cache-Control "public, immutable";
add_header Access-Control-Allow-Origin "*";
access_log off;
}
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml application/javascript
application/json application/xml image/svg+xml;
กด OK แล้วตรวจว่าคอนฟิกถูกต้อง Plesk จะแจ้งข้อผิดพลาดทันทีหากไวยากรณ์ผิด
sudo nginx -t
curl -sI https://example.com/wp-content/themes/mytheme/style.css | grep -i 'cache-control\|expires'
ขั้นตอนที่ 3: เปิดแคชหน้าเว็บ (Nginx Caching)
ขั้นตอนนี้มีผลมากที่สุดแต่ต้องระวังที่สุด เพิ่มในช่อง Additional nginx directives
# ประกาศพื้นที่แคช ต้องอยู่ที่ระดับ http จึงต้องใส่ในคอนฟิกส่วนกลางแทน
# ดูขั้นตอนที่ 4
set $skip_cache 0;
# ไม่แคชเมื่อไม่ใช่ GET
if ($request_method != GET) { set $skip_cache 1; }
# ไม่แคชหน้าที่ต้องเป็นส่วนตัว
if ($request_uri ~* "/(wp-admin|wp-login\.php|cart|checkout|my-account)") {
set $skip_cache 1;
}
# ไม่แคชผู้ที่ล็อกอินหรือมีของในตะกร้า
if ($http_cookie ~* "wordpress_logged_in|woocommerce_items_in_cart|wp_woocommerce_session_|comment_author") {
set $skip_cache 1;
}
location / {
proxy_cache plesk_cache;
proxy_cache_valid 200 301 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status always;
proxy_pass http://127.0.0.1:7080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
ขั้นตอนที่ 4: ประกาศพื้นที่แคชที่ระดับเซิร์ฟเวอร์
คำสั่ง proxy_cache_path ต้องอยู่ในบล็อก http ซึ่งใส่ในหน้า Plesk ไม่ได้ ต้องสร้างไฟล์แยก
sudo nano /etc/nginx/conf.d/zz-plesk-cache.conf
proxy_cache_path /var/cache/nginx/plesk
levels=1:2
keys_zone=plesk_cache:20m
max_size=2g
inactive=60m
use_temp_path=off;
sudo mkdir -p /var/cache/nginx/plesk
sudo chown nginx:nginx /var/cache/nginx/plesk
sudo nginx -t && sudo systemctl reload nginx
ระวัง การอัปเดต Plesk อาจเขียนทับไฟล์ในบางโฟลเดอร์ ใช้ชื่อไฟล์ที่ขึ้นต้นด้วย zz เพื่อให้โหลดทีหลังและตรวจหลังอัปเดต Plesk ทุกครั้ง
ขั้นตอนที่ 5: ทดสอบว่าแคชทำงานและปลอดภัย
# ครั้งแรกควรเป็น MISS ครั้งที่สองควรเป็น HIT
curl -sI https://example.com/ | grep -i x-cache-status
curl -sI https://example.com/ | grep -i x-cache-status
# ผู้ที่ล็อกอินต้องได้ BYPASS
curl -sI -H 'Cookie: wordpress_logged_in_abc=1' https://example.com/ | grep -i x-cache-status
# หน้าตะกร้าต้องได้ BYPASS
curl -sI https://example.com/cart/ | grep -i x-cache-status
ทดสอบด้วยสองเบราว์เซอร์เสมอ ใส่สินค้าลงตะกร้าในเบราว์เซอร์แรก แล้วเปิดเว็บในเบราว์เซอร์ที่สองแบบไม่ระบุตัวตน ตะกร้าต้องว่าง หากเห็นสินค้าแปลว่าแคชผิดและต้องปิดทันที