nginx njs: ติดตั้งโมดูล ตั้งค่า js_set และใช้ reload เพื่อสร้างตัวแปร JavaScript

nginx njs เป็นโมดูลทางการของ nginx ที่ใช้ฟังก์ชัน JavaScript ในการตั้งค่า nginx เพื่อประมวลผลคำขอหรือสร้างค่าตัวแปร บนเซิร์ฟเวอร์ Nginx + Apache เพื่อให้ตัวพิมพ์เล็กใหญ่ของ URL คำขอตรงกัน ซึ่งการตั้งค่า nginx อย่างเดียวเปลี่ยนไม่ได้ จึงติดตั้งโมดูล njs ในเวอร์ชันเดียวกับ nginx ที่ติดตั้งอยู่ แล้วใส่ตัวแปรที่สร้างด้วย js_set ลงในพาธไฟล์แคช และใช้ reload โดยไม่ต้องรีสตาร์ต
ฟังก์ชันตัวอย่างเป็นแบบบรรทัดเดียวที่เปลี่ยนการเข้ารหัสเปอร์เซ็นต์ของ URL ภาษาเกาหลีเป็นตัวพิมพ์เล็ก ส่วนการอ่านค่าเฮดเดอร์หรืออาร์กิวเมนต์จากอ็อบเจ็กต์คำขอมาสร้างตัวแปรก็ทำแบบเดียวกัน
1️⃣ nginx njs คืออะไร: โมดูลที่ขยายความสามารถของ nginx ด้วย JavaScript
njs ไม่ใช่สภาพแวดล้อมรัน JavaScript ที่ทำงานเองได้อย่าง Node.js ไม่มีสคริปต์เริ่มต้นหรือ event loop ของตัวเอง โค้ดจะรันเฉพาะเมื่อ nginx เรียกฟังก์ชันที่ระบุไว้ในการตั้งค่า แล้วการประมวลผลก็กลับไปที่ nginx
จุดที่ nginx เรียกฟังก์ชัน JavaScript ถูกกำหนดไว้แล้ว ได้แก่ ขั้นประมวลผลคำขอและการตอบกลับ HTTP ขั้นประมวลผลเซสชัน TCP·UDP การคำนวณค่าตัวแปร และตัวจับเวลาแบบรอบ ฟังก์ชันจะอ่าน URL เฮดเดอร์ และอาร์กิวเมนต์จากอ็อบเจ็กต์คำขอที่ nginx ส่งให้ แล้วคืนผลเป็นการตอบกลับหรือค่าตัวแปร
ฝั่ง HTTP ใช้ [js_import] โหลดไฟล์สคริปต์ [js_set] สร้างค่าตัวแปร [js_content] สร้างเนื้อหาการตอบกลับ และ [js_header_filter] กับ [js_body_filter] แก้เฮดเดอร์และเนื้อหาการตอบกลับ ไดเรกทีฟที่ใช้ครั้งนี้มีสองตัว คือ [js_import] และ [js_set]
เอนจินพื้นฐานของโมดูล njs รองรับ ECMAScript 5.1 (strict mode) บวกฟีเจอร์บางส่วนของ ECMAScript 6 ขึ้นไป การจัดการสตริงระดับแทนที่ด้วย regex และฟังก์ชันทำงานได้ในขอบเขตนี้
2️⃣ เมื่อไรต้องใช้ njs: ค่าตัวแปรที่การตั้งค่า nginx อย่างเดียวเปลี่ยนไม่ได้
ปลั๊กอิน WordPress อย่าง WP Rocket ตั้งชื่อโฟลเดอร์แคชของบทความที่มี URL ภาษาเกาหลีด้วยการเข้ารหัสเปอร์เซ็นต์ตัวพิมพ์เล็ก แต่เบราว์เซอร์ส่งคำขอ URL เดียวกันที่เข้ารหัสเป็นตัวพิมพ์ใหญ่ เซิร์ฟเวอร์นี้มีเว็บไซต์ WordPress ทำงานอยู่
ถ้า nginx สร้างพาธไฟล์แคชจาก URL คำขอตามที่เป็น ตัวพิมพ์เล็กใหญ่จะไม่ตรงกัน หาไฟล์ไม่เจอ และคำขอจะถูกส่งต่อไปยัง Apache และ PHP
การตั้งค่า nginx อย่างเดียวเปลี่ยนค่านี้เป็นตัวพิมพ์เล็กไม่ได้ [map] เลือกได้แค่ค่าหนึ่งจากค่าที่กำหนดไว้ แปลงสตริงไม่ได้ และก่อนติดตั้ง ผลของ [nginx -V] และโฟลเดอร์โมดูลก็ไม่มีโมดูล perl หรือ lua
ถ้ามี URL ที่ต้องเปลี่ยนแค่ไม่กี่รายการ ตารางจับคู่ [map] ก็จัดการได้ แต่ต้องสร้างตารางใหม่และ reload ทุกครั้งที่มีบทความใหม่ ถ้าทุก URL ต้องแปลงค่าด้วยกฎเดียวกัน ฟังก์ชัน [js_set] ตัวเดียวก็ครอบคลุมถึง URL ของบทความใหม่ แท็ก และหมวดหมู่

[perl_set] ของโมดูล perl ใช้ที่จุดเดียวกันได้ และรีโพสิทอรีก็มีแพ็กเกจที่จับคู่กับ nginx แต่คู่มือทางการของ nginx ระบุว่าโมดูล perl เป็นโมดูลทดลอง
3️⃣ ติดตั้ง nginx njs: ในเวอร์ชันเดียวกับ nginx ที่ติดตั้งอยู่
การติดตั้งด้วยชื่อแพ็กเกจโมดูลอย่างเดียวดูเหมือนจะเพิ่มแค่ njs แต่ njs ล่าสุดในรีโพสิทอรีต้องใช้ nginx ล่าสุด nginx จึงถูกอัปเกรดไปด้วย ในการตรวจก่อนติดตั้ง คำสั่งติดตั้งที่ไม่ระบุเวอร์ชันแสดงแผนอัปเกรด nginx จาก 1.28.0 เป็น 1.30.6
จึงต้องตรวจเวอร์ชันของ nginx ที่ติดตั้งอยู่ตอนนี้ก่อน
rpm -q nginxnginx-1.28.0-1.el9.ngx.x86_64รีโพสิทอรีมีแพ็กเกจ njs แยกสำหรับ nginx แต่ละเวอร์ชัน ในหมายเลขเวอร์ชัน ส่วนหน้า + คือเวอร์ชันของ nginx และส่วนหลังคือเวอร์ชันของ njs
dnf list --showduplicates nginx-module-njs | grep '1.28.0+'nginx-module-njs.x86_64 1:1.28.0+0.9.4-1.el9.ngx @nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.8.10-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.0-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.1-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.2-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.3-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.4-1.el9.ngx nginx-stableเวอร์ชันที่จับคู่กับ nginx 1.28.0 มีหกเวอร์ชันตั้งแต่ 0.8.10 ถึง 0.9.4 และบรรทัด @nginx-stable บนสุดคือเวอร์ชันที่ติดตั้งเสร็จแล้ว การติดตั้งใช้เวอร์ชันล่าสุดคือ 0.9.4 โดยระบุหมายเลขเวอร์ชันเต็ม
dnf install nginx-module-njs-1:1.28.0+0.9.4-1.el9.ngxตรวจเวอร์ชัน nginx ที่แพ็กเกจที่ติดตั้งต้องการได้ด้วย rpm
rpm -q --requires nginx-module-njs | grep nginxnginx-r1.28.0rpm -ql nginx-module-njs | grep -v build-id/usr/bin/njs
/usr/lib64/nginx/modules/ngx_http_js_module-debug.so
/usr/lib64/nginx/modules/ngx_http_js_module.so
/usr/lib64/nginx/modules/ngx_stream_js_module-debug.so
/usr/lib64/nginx/modules/ngx_stream_js_module.so
/usr/share/doc/nginx-module-njs
/usr/share/doc/nginx-module-njs/CHANGES
/usr/share/doc/nginx-module-njs/COPYRIGHTไฟล์ที่ติดตั้งคือโมดูล HTTP โมดูล stream ที่จัดการ TCP·UDP เวอร์ชันดีบักของแต่ละโมดูล และเครื่องมือบรรทัดคำสั่ง njs การตั้งค่าครั้งนี้โหลดเพียงไฟล์เดียว คือโมดูล HTTP [ngx_http_js_module.so]
4️⃣ ตั้งค่า js_set: ตั้งแต่โหลดโมดูลจนถึงพาธไฟล์แคช
ติดตั้งแพ็กเกจแล้ว nginx ก็ไม่โหลดโมดูลให้อัตโนมัติ ต้องมีบรรทัด [load_module] ที่บนสุดของ nginx.conf ตามคู่มือทางการ [load_module] เป็นไดเรกทีฟในบริบท main จึงวางไว้นอกบล็อก events·http
# บนสุดของ /etc/nginx/nginx.conf (นอกบล็อก events·http)
load_module modules/ngx_http_js_module.so;ฟังก์ชันแปลงเก็บไว้ในไฟล์ .js แยกจากไฟล์ตั้งค่า และการตั้งค่า nginx จะโหลดฟังก์ชันที่ส่งออกด้วย export default ในบรรทัดสุดท้าย
// /etc/nginx/njs/rocket.js — เปลี่ยนเฉพาะการเข้ารหัสเปอร์เซ็นต์ %XX เป็นตัวพิมพ์เล็ก
function lc(r) {
return r.variables.request_uri.replace(/%[0-9A-F]{2}/g, function (m) { return m.toLowerCase(); });
}
export default { lc };ฟังก์ชันอ่านตัวแปร [request_uri] จากอ็อบเจ็กต์คำขอ r แล้วเปลี่ยนเฉพาะสองตัวหลังเครื่องหมายเปอร์เซ็นต์ที่เป็นตัวพิมพ์ใหญ่ให้เป็นตัวพิมพ์เล็กก่อนคืนค่า ตัวอักษรละตินไม่ถูกแตะ URL ภาษาอังกฤษที่มีตัวพิมพ์ใหญ่ปนจึงไม่เปลี่ยน และตรงกับกฎที่ WP Rocket ใช้ตั้งชื่อโฟลเดอร์แคช
# ในบล็อก http (ไฟล์ .conf ใน conf.d)
js_import rkt from /etc/nginx/njs/rocket.js;
js_set $rocket_uri rkt.lc;rkt ใน [js_import] คือชื่อที่ใช้เรียกฟังก์ชันในโมดูล และ [js_set] ทำให้ผลของฟังก์ชันนั้นเป็นตัวแปร [$rocket_uri] ตามคู่มือทางการ ฟังก์ชันนี้รันเมื่อมีการอ้างถึงตัวแปรครั้งแรกในคำขอ และรองรับเฉพาะการประมวลผลแบบซิงโครนัส
# บล็อก server — เปลี่ยน $request_uri ในพาธไฟล์แคชเป็น $rocket_uri
set $rocket_file '/wp-content/cache/wp-rocket/example.com${rocket_uri}index$rocket_mobile-https.html';ที่เปลี่ยนมีเพียงบรรทัดเดียวที่สร้างพาธไฟล์แคช ส่วนเงื่อนไขที่ยกเว้นคุกกี้ล็อกอิน คิวรี และคำขอ POST ออกจากแคชยังคงเดิม
5️⃣ ใช้งานและตรวจ: บันทึกข้อผิดพลาดและเฮดเดอร์การตอบกลับหลัง reload
รันการทดสอบการตั้งค่าก่อน ถ้าผ่านจึง reload
nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulsystemctl reload nginxบรรทัด [load_module] ที่เพิ่มใหม่มีผลด้วย reload โดยไม่ต้องรีสตาร์ต บันทึกข้อผิดพลาดมีบรรทัดการเริ่มต้นเครื่องเสมือน njs และไม่มีข้อผิดพลาดของ JavaScript
grep 'js vm init' /var/log/nginx/error.log | head -12026/10/17 18:21:35 [notice] 27992#27992: js vm init njs: 0000559FDF6D0E00njs ท้ายบรรทัดคือชื่อเอนจินที่ใช้อยู่ บรรทัดเดียวกันนี้ถูกบันทึกตอนตรวจการตั้งค่าด้วย [nginx -t] ด้วย จึงต้องดูให้ตรงกับเวลาที่ reload
curl -sI 'https://example.com/-/' | grep -i 'x-rocket\|content-type'content-type: text/html
x-rocket-nginx-serving-file: HITแม้ URL ภาษาเกาหลีที่เข้ารหัสเป็นตัวพิมพ์ใหญ่ก็มีเฮดเดอร์บอกว่า nginx ตอบด้วยไฟล์แคช คำขอที่มีคิวรีหรือคุกกี้ล็อกอินและคำขอ POST ยังส่งต่อไปยัง PHP โดยไม่มีเฮดเดอร์นี้หลังการเปลี่ยน
6️⃣ ย้อนกลับ njs และอัปเดต nginx
เวลาย้อนกลับ ให้เปลี่ยน [$rocket_uri] ในพาธไฟล์แคชกลับเป็น [$request_uri] เอาไฟล์ตั้งค่า [js_import]·[js_set] และบรรทัด [load_module] ออก แล้วทดสอบการตั้งค่าก่อน reload
# บล็อก server — กลับไปใช้ตัวแปรเดิม
set $rocket_file '/wp-content/cache/wp-rocket/example.com${request_uri}index$rocket_mobile-https.html';เก็บแพ็กเกจไว้ก็ได้ ถ้าไม่มีบรรทัด [load_module] nginx ก็ไม่โหลด จะถอนแพ็กเกจเฉพาะเมื่อต้องการลบออกทั้งหมด
dnf remove nginx-module-njsเมื่ออัปเดต nginx แพ็กเกจ njs ก็ต้องอัปเป็นเวอร์ชันที่จับคู่กับ nginx ใหม่ด้วย ก่อนอัปเดตให้ตรวจด้วย [dnf list --showduplicates] ว่าในรีโพสิทอรีมี njs คู่ของ nginx เวอร์ชันใหม่หรือไม่
🔢 FAQ & เนื้อหาแนะนำ














ℹ️ ประกาศเรื่องลิงก์แอฟฟิลิเอต
เนื้อหาของเว็บไซต์นี้มีลิงก์แอฟฟิลิเอต หากผู้เข้าชมซื้อสินค้าหรือบริการผ่านลิงก์เหล่านี้ เว็บไซต์นี้จะได้รับค่าคอมมิชชันจากผู้ขาย ในกระบวนการนี้ ราคาที่ผู้ซื้อจ่าย(ราคาจะลดลงเมื่อมีโปรโมชัน↓)จะไม่สูงขึ้นแต่อย่างใด ราคา ส่วนลด และข้อมูลสต็อกที่แสดงเป็นข้อมูล ณ เวลาที่เขียนและอาจต่างจากความเป็นจริง โปรดตรวจสอบกับผู้ขายอีกครั้งก่อนซื้อ การเลือกและการประเมินสินค้าเขียนตามเกณฑ์ของเราเอง และการได้รับค่าคอมมิชชันหรือไม่ไม่มีผลต่อลำดับการแนะนำหรือเนื้อหาการประเมิน

