หยุดทำการบีบอัด JSON ผิดลำดับ: minify vs gzip vs brotli วัดผลจริง
สรุปสำคัญ: Minify ลดขนาด JSON ดิบได้ 30-50% แต่ gzip กลืนกำไรนั้นไปเกือบหมด ตัวเลขวัดจริงจากรูปแบบข้อมูลหลากหลาย พร้อมสี่กรณีที่ minify ทำให้แย่ลง

สรุปสั้น: แยกการบีบอัดเพื่อการขนส่งออกจากการตัดโครงสร้างก่อน หากยังไม่ได้เปิด gzip หรือ brotli ให้แก้คอนฟิกเซิร์ฟเวอร์ — gzip -6 เพียงอย่างเดียวไปถึง 94.5% และทำให้ minify มีค่าเพียง 0.9 จุด ตัวเลข 46.3% เต็ม ๆ ของ minify จะเกิดผลก็ต่อเมื่อบัญชีไบต์ถูกบันทึกในเครื่อง: request body, Lambda 6 MB, Firestore 1 MiB หรือ JSON ที่เขียนลงดิสก์และ log
ป้าย "ประหยัด 35%" บน minifier ที่คุณชื่นชอบนั้นซื่อสัตย์ — มันวัดไบต์ดิบ API ของคุณทำงานอยู่บน gzip หรือ brotli และทั้งสองกลืนความซ้ำซ้อนแบบเดียวกันนั้นไป คูณตัวเลขสองตัวเข้าด้วยกันแล้วคุณจะได้คำตอบที่ผิด
1. แยก "การบีบอัด" ออกเป็นสองสิ่งที่ต่างกัน
สิ่งที่ผู้คนเรียกว่าการบีบอัด JSON จริง ๆ แล้วเป็นการดำเนินการสองอย่างที่ไม่เกี่ยวข้องกัน และการสับสนระหว่างสองอย่างนี้คือต้นทางของข้อสรุปผิดทุกข้อ
| minify (ตัดช่องว่าง) | gzip / brotli (บีบอัดเพื่อขนส่ง) | |
|---|---|---|
| ธรรมชาติ | การแปลงเอกสาร | การแปลงการขนส่ง |
| เอาต์พุต | ข้อความ JSON ที่ยังถูกต้องและอ่านได้ | ไบนารี ใช้ไม่ได้จนกว่าจะถอดรหัส |
| กำไรเกิดที่ไหน | ดิสก์ หน่วยความจำ log ขีดจำกัดขนาด | เฉพาะบนสายและใน cache |
| หลังถอดรหัส | ไบต์ยังเล็กลง | ไบต์กลับไปมีขนาดเดิม |
| ใครเป็นเจ้าของ | สคริปต์ build ของคุณ อาร์กิวเมนต์ serializer | Nginx, CDN, เฟรมเวิร์กเซิร์ฟเวอร์ |
สองแถวสุดท้ายคือแถวที่สำคัญ ขีดจำกัดของแพลตฟอร์มถูกวัด หลังถอดรหัส: เพดาน payload 6 MB ของ AWS Lambda, เพดาน 1 MiB ต่อเอกสารของ Firestore การเปิด gzip ไม่ได้ซื้อไบต์แม้แต่ไบต์เดียวตรงนั้น เพราะทั้งสองนับผลลัพธ์ที่ถอดรหัสแล้ว
2. minify ตัดทิ้งเพียงสิ่งเดียว: ช่องว่างเชิงโครงสร้าง
RFC 8259 อนุญาตช่องว่าง (space, \t, \n, \r) รอบอักขระเชิงโครงสร้างใด ๆ ไม่มีสิ่งอื่นในเอกสาร JSON ที่เป็นทางเลือก: ชื่อคีย์คือข้อมูล ตัวเลขเก็บทุกหลัก และเนื้อหาสตริงแตะต้องไม่ได้แม้แต่ไบต์เดียว
นั่นทำให้การดำเนินการทั้งหมดเป็นบรรทัดเดียว:
const minified = JSON.stringify(JSON.parse(pretty));
// RFC 8259 อนุญาตช่องว่างเฉพาะรอบอักขระเชิงโครงสร้าง
// ดังนั้นช่องว่างภายในสตริงคือข้อมูล ไม่ใช่การจัดรูปแบบ
JSON.stringify(JSON.parse('{"note": "two spaces"}'));
// {"note":"two spaces"} - ช่องว่างภายในทั้งสองตำแหน่งยังอยู่
สิ่งที่ควรระบุคือการดำเนินการสามอย่างที่ถูกจัดเข้าใต้ "การบีบอัด" แต่จริง ๆ แล้วแก้ไขเอกสาร: การตัดคีย์ที่ค่าเป็น null, การปัดเศษทศนิยม และการเรียงคีย์ใหม่ สิ่งเหล่านี้เปลี่ยนเอกสารแทนที่จะจัดรูปแบบใหม่ ดังนั้นเครื่องมือใดที่โฆษณา "deep compression" ต้องได้รับความยินยอมจากผู้บริโภคข้อมูลของคุณก่อนจะเปิดใช้
เนื่องจาก minify ตัดทิ้งเพียงช่องว่าง ผลตอบแทนจึงขึ้นกับ สัดส่วนของไฟล์ที่เป็นการย่อหน้า เกือบทั้งหมด คาดว่าสิ่งนี้จะปรากฏซ้ำ ๆ ในตารางด้านล่าง
3. การวัด: เอกสารสี่ฉบับ สามระดับ gzip บวก brotli
สภาพแวดล้อม: Node v22.13.1, zlib.gzipSync ที่ระดับ 1 / 6 / 9, brotliCompressSync ที่คุณภาพเริ่มต้น (11) ตัวอย่างทั้งสี่ตั้งใจครอบคลุมรูปแบบที่คุณส่งจริง: คำสั่งซื้อซ้อนกัน 50 รายการ (โครงสร้างลึก คีย์ซ้ำ), คอนฟิก 6 ระดับ (คีย์ยาว ค่าสั้น), อาร์เรย์ log 200 บรรทัด (สตริงยาว แทบไม่มีการย่อหน้า) และ media-manifest.json จริงจากไซต์นี้ (รูปแบบผสม สตริงที่มี URL หนาแน่น)
ขั้นแรก: ไบต์ดิบ
| ตัวอย่าง | pretty (2 ช่องว่าง) | pretty (4 ช่องว่าง) | หลัง minify | minify ประหยัด |
|---|---|---|---|---|
| คำสั่งซื้อซ้อนกัน 50 รายการ | 29,551 B | 40,761 B | 15,881 B | 46.3% |
| คอนฟิก 6 ระดับ | 25,450 B | 38,012 B | 11,679 B | 54.1% |
| อาร์เรย์ log 200 บรรทัด | 14,582 B | 14,982 B | 13,981 B | 4.1% |
| media-manifest.json | 25,149 B | 28,114 B | 21,222 B | 15.6% |
นี่คือที่มาของป้าย "ประหยัด 35%" และมันไม่ได้โกหก ปัญหาปรากฏในขั้นที่สอง
ขั้นที่สอง: บีบอัดแต่ละรูปแบบ แล้วถามว่า minify ยังเพิ่มอะไรได้อีก
| ตัวอย่าง | บน gzip -1 | บน gzip -6 | บน gzip -9 | บน brotli |
|---|---|---|---|---|
| คำสั่งซื้อซ้อนกัน 50 รายการ | 21.0% | 17.0% | 8.9% | 10.6% |
| คอนฟิก 6 ระดับ | 74.2% | 59.1% | 58.0% | 56.4% |
| อาร์เรย์ log 200 บรรทัด | -0.7% | -0.4% | 0.6% | -0.3% |
| media-manifest.json | 1.5% | 1.0% | 1.0% | 1.6% |
เอกสารคำสั่งซื้อซ้อนกันฉบับเดียวกันที่สูญเสีย 46.3% ของไบต์ดิบ เก็บไว้ได้เพียง 17.0% ของส่วนนั้นเมื่อ gzip -6 เข้ามาเกี่ยว อาร์เรย์ log กลายเป็นค่าลบเลย: minify-แล้ว-บีบอัดมีขนาดใหญ่กว่าการบีบอัดต้นฉบับ pretty เล็กน้อย การเป็นค่าลบไม่ใช่บั๊ก มันคือสิ่งที่คุณควรคาดหวัง และหัวข้อถัดไปอธิบายว่าทำไม
ขั้นที่สาม: การลดลงทั้งหมดเทียบกับเอกสาร pretty ต้นฉบับ — ตัวเลขที่เดินทางบนสายจริง
| ตัวอย่าง | gzip -6 อย่างเดียว | minify + gzip -6 | minify + brotli |
|---|---|---|---|
| คำสั่งซื้อซ้อนกัน 50 รายการ | 94.5% | 95.4% | 96.9% |
| คอนฟิก 6 ระดับ | 96.0% | 98.4% | 99.0% |
| อาร์เรย์ log 200 บรรทัด | 89.9% | 89.9% | 95.0% |
| media-manifest.json | 83.5% | 83.6% | 86.1% |
4. ทำไม gzip กลืนเครดิตของ minify
gzip คือ LZ77 ตามด้วย Huffman coding การเคลื่อนไหวหลักของ LZ77 คือ "มองย้อนกลับไปในหน้าต่าง 32 KB หาลำดับที่ซ้ำ แล้วแทนด้วย pointer (ระยะทาง, ความยาว)" การย่อหน้าเป็นเป้าหมายที่ง่ายที่สุดสำหรับการเคลื่อนไหวนั้น: ทุกระดับการซ้อนปล่อยชุดช่องว่างที่เหมือนกัน และบรรทัดที่อยู่ติดกันหลายสิบบรรทัดซ้ำรูปแบบเดียวกัน Huffman จากนั้นกำหนดรหัสสั้นให้สัญลักษณ์ที่ใช้บ่อย ดังนั้นรูปแบบอย่าง \n บวกช่องว่างแปดช่อง — ซึ่งอาจเกิดซ้ำพันครั้งในไฟล์เดียว — สุดท้ายมีต้นทุนเพียงสองหรือสามบิต
ดังนั้นไบต์ที่ minify ลบออกคือไบต์ที่ตัวบีบอัดจะยุบให้เกือบฟรีอยู่แล้ว การทำเองหมายถึงการทำงานซ้ำในสิ่งที่ตัวบีบอัดเก่งอยู่แล้ว และ 46% ของคุณจะยุบลงเหลือ 17% นั่นคือเรื่องราวทั้งหมดเบื้องหลังตารางด้านบน
ผลลัพธ์ค่าลบของอาร์เรย์ log สมควรได้คำอธิบายของตัวเอง ตัวอย่างนั้นเป็นสตริงยาวเกือบทั้งหมด (บรรทัด log, URL, base64) ซึ่งหมายถึงการซ้ำน้อยและเอนโทรปีสูง — มีความซ้ำซ้อนให้ตัวบีบอัดกำจัดน้อยอยู่แล้ว ตัวขึ้นบรรทัดใหม่ในฉบับ pretty บังเอิญให้ขอบเขตที่มั่นคงแก่ตัวจับคู่ เมื่อลบออก LZ77 จะสูญเสียจุดยึดเหล่านั้น: ในตัวอย่างนี้ การบีบอัดต้นฉบับ pretty ที่ gzip -1 ให้ 1,508 ไบต์ ขณะที่ minify-แล้ว-บีบอัดให้ 1,518 ไบต์ แย่กว่า 10 ไบต์
เรียงตามขนาด คันโยกเรียงลำดับได้ดังนี้:
| คันโยก | ประหยัดเทียบเอกสาร pretty ต้นฉบับ (คำสั่งซื้อซ้อนกัน) | ต้นทุน |
|---|---|---|
| minify | 46.3% (ไบต์ดิบเท่านั้น) | สูญเสียความอ่านง่าย ต้องมีขั้นตอน build |
| gzip -6 | 94.5% | CPU เซิร์ฟเวอร์เล็กน้อย คอนฟิกเกือบศูนย์ |
| minify + gzip -6 | 95.4% | สองอย่างข้างบนรวมกัน |
| minify + brotli | 96.9% | ต้องมี HTTPS และโมดูล brotli; pre-compress สินทรัพย์ static |
การกระโดดจาก 0 ไป 94.5% คืองานของ gzip การกระโดดจาก 94.5% ไป 95.4% — เก้าในสิบของจุดหนึ่ง — คืองานของ minify ตารางนี้ชี้ว่าความพยายามของคุณควรอยู่ที่ไหน
5. ระดับการบีบอัดคือตัวแปรที่ซ่อนอยู่
ข้อโต้แย้งใดที่สมมติระดับ gzip คงที่เพียงค่าเดียวล้วนยืนอยู่บนทราย เพราะระดับเปลี่ยนมูลค่าเพิ่มของ minify โดยตรง:
| การตั้งค่าการขนส่ง | ไบต์เพิ่มที่ minify ยังประหยัดได้ (คำสั่งซื้อซ้อนกัน) |
|---|---|
gzip -1 (gzip_comp_level เริ่มต้นของ Nginx) |
21.0% |
| gzip -6 (ค่าเริ่มต้นในไลบรารีมาตรฐานส่วนใหญ่) | 17.0% |
| gzip -9 | 8.9% |
| brotli (คุณภาพเริ่มต้น) | 10.6% |
การบีบอัดเพื่อขนส่งยิ่งอ่อน minify ยิ่งได้ผล นั่นให้กฎปฏิบัติ: บน Nginx ที่ติดตั้งปกติซึ่ง gzip_comp_level ยังเป็น 1, minify ให้ 21% เมื่อปรับเป็น 9 หรือเปลี่ยนไป brotli แล้ว มันลดลงเหลือ 9-11% และปกติคุณข้ามได้
ก่อนจะเถียงไปทางใด ให้วัดว่าคุณอยู่ระดับใดจริง ๆ:
# ดึง response เดียวกันด้วย Accept-Encoding สามค่า แล้วเทียบสิ่งที่นับได้
for enc in identity gzip br; do
size=$(curl -s -o /dev/null -w '%{size_download}' \
-H "Accept-Encoding: $enc" https://api.example.com/v1/orders)
echo "$enc -> $size bytes"
done
ตัวเลขสามตัวตอบสามคำถามพร้อมกัน: การบีบอัดเปิดอยู่หรือไม่ ระดับใด และเหลือที่ว่างให้ minify แค่ไหน หาก identity และ gzip กลับมาใกล้กันมาก การบีบอัดไม่ได้ทำงานเลย — และสิ่งที่ต้องแก้คือ Nginx ไม่ใช่ JSON ของคุณ:
gzip on;
gzip_comp_level 6;
gzip_min_length 256; # ข้าม response เล็ก ๆ มันมีแต่โตขึ้น
gzip_types application/json application/javascript text/css;
6. เมื่อ minify คุ้มค่าจริง ๆ
การทดสอบหนึ่งข้อตัดสินได้: ไบต์ที่คุณประหยัดจะถูกบันทึกที่ไหนสักแห่ง หรือคุณจะชนขีดจำกัดที่นับไบต์ดิบหรือไม่? หากใช่ 46% เต็ม ๆ จะเกิดผล หากคำตอบคือ "มันอยู่บนสายเท่านั้น" 17% คือมูลค่าจริงของมัน
หนึ่ง HTTP request body เซิร์ฟเวอร์ส่วนใหญ่ไม่ถอดรหัส request body และ gzip ถูกตั้งค่าเกือบเฉพาะกับ response JSON ที่คุณ POST ปกติไม่มีการป้องกันระดับการขนส่งเลย ดังนั้นการประหยัดของ minify มาถึงในราคาเต็ม เช่นเดียวกับ webhook callback, MQTT telemetry และ WebSocket frame ที่ไม่ได้เจรจา permessage-deflate
สอง ช่องทางที่มีเพดานไบต์แข็ง — และทุกช่องนับไบต์ ที่ถอดรหัสแล้ว:
| ช่องทาง | ขีดจำกัด | gzip ช่วยได้หรือไม่ |
|---|---|---|
| AWS Lambda synchronous payload | 6 MB | ไม่ได้ วัดหลังถอดรหัส |
| Firestore เอกสารเดียว | 1 MiB | ไม่ได้ |
| Kafka ข้อความเดียว (ค่าเริ่มต้น) | 1 MB | ไม่ได้ การบีบอัดฝั่ง broker เป็นอีกชั้น |
| โควตา localStorage | ~5 MB (นับเป็นตัวอักษร) | ไม่ได้ |
| URL ของ GET request | ขึ้นกับเซิร์ฟเวอร์ ปกติ 8 KB | ไม่ได้ |
ในหมวดนี้ minify ไม่ใช่การปรับแต่ง แต่คือความแตกต่างระหว่างคำขอที่ส่งได้กับคำขอที่ล้มเหลว การฝัง JSON ใน query string ของ URL เป็นกรณีที่คมที่สุด: URL ไม่เคยถูกบีบอัดและมีเพดานความยาวจริง ดังนั้น minify ก่อน แล้วค่อยตัดสินใจว่าต้องใช้ base64 หรือไม่
สาม JSON ที่เขียนลงดิสก์หรือ log Log และดัชนีเก็บไบต์ตามตัวอักษรโดยไม่มีชั้นการขนส่งเข้ามาเกี่ยวข้อง มีข้อแม้ที่ทำให้คนสะดุด: minify ช่วยได้ก็ต่อเมื่อคุณเขียน JSON แบบ pretty อยู่แต่แรก ตัวอย่าง log 200 บรรทัดนั้นประหยัดเพียง 4.1% เพราะบรรทัดของมันกระชับอยู่แล้วและการย่อหน้ามีแทบไม่มีในไฟล์ ตรงกันข้าม หาก logger ของคุณเรียก JSON.stringify(obj, null, 2) การตัดอาร์กิวเมนต์ที่สามออกคือเงินฟรี
หมายเหตุสุดท้าย: เมื่อไบต์ดิบตึงจริง ๆ ชื่อคีย์มักเป็นคันโยกที่ใหญ่กว่าการย่อหน้า บน media-manifest.json การแทนคีย์ที่ไม่ซ้ำ 14 ตัวด้วย k0 ถึง k13 ทำให้รูปแบบ minified ลดจาก 21,222 B เหลือ 18,887 B — อีก 11.0% เมื่อบีบอัด ขอบที่เหลือนั้นหดเหลือ 2.4% ใต้ gzip -6 และ 1.3% ใต้ brotli กลไกเดียวกับทุกอย่างข้างบน: การย่อหน้าและชื่อคีย์ต่างเป็นข้อมูลโครงสร้างที่ซ้ำกัน และตัวบีบอัดรับเงินปันผลเดียวกันไม่ว่าทางใด
7. สี่กรณีที่มันย้อนกลับมาแย่
อย่า minify ไฟล์ที่คุณ commit เปลี่ยน "qty": 2 เป็น 3 แล้วไฟล์ pretty แสดงบรรทัดสะอาดหนึ่งบรรทัดใน git diff; ไฟล์ minified เขียนบรรทัดใหม่ทั้งบรรทัด และเมื่อมีหลายร้อยฟิลด์คุณหาการเปลี่ยนแปลงไม่เจอเลย นี่คือกลไกเดียวกับที่กล่าวใน วิธีแก้ conflict การ merge JSON — เครื่องมือ diff ทำงานทีละบรรทัด ดังนั้น JSON บรรทัดเดียวทำให้ทุกการแก้ไขกลายเป็น "ทั้งบรรทัดต่างกัน" เก็บไฟล์ pretty ใน repository และ minify เฉพาะใน build output หรือเมื่อเขียนลง storage
อย่าบีบอัด response เล็ก ๆ Response ที่มีเพียง {"ok": true} มีขนาด 16 ไบต์เมื่อเพิ่มการย่อหน้า และ 36 ไบต์หลัง gzip -6 — ใหญ่กว่า ยี่สิบไบต์ เพราะ dictionary และ header ของ gzip เองกินพื้นที่ นี่ไม่ใช่ทฤษฎี; มันคือเหตุผลที่ gzip_min_length มีอยู่ ค่าเริ่มต้น 20 ไบต์ใน Nginx ต่ำเกินไปสำหรับ production ซึ่ง 256 คือค่าพื้นฐานปกติ
อย่าคาดหวังการแยกวิเคราะห์ที่เร็วขึ้น เมื่อขยายชุดคำสั่งซื้อเดียวกันเป็น 4,000 เรกคอร์ด เอกสาร pretty คือ 2,374,378 ไบต์เทียบกับ 1,282,358 ไบต์ minified — เล็กลง 46% — แต่เวลามัธยฐานของ JSON.parse เคลื่อนจาก 5.7 ms เป็น 5.0 ms เท่านั้น เร็วขึ้นประมาณ 12% การลดขนาดครึ่งหนึ่งไม่ได้ลดเวลาครึ่งหนึ่ง เพราะ parser ใช้เวลาเกือบทั้งหมดในการ slice สตริงและแปลงตัวเลข การข้ามช่องว่างเป็นเพียงเรื่องประกอบ สิ่งที่ขับเคลื่อนต้นทุนการแยกวิเคราะห์จริง ๆ คือจำนวนคีย์และเนื้อหาสตริง ซึ่ง การแยกวิเคราะห์ การเรนเดอร์ และการสตรีมไฟล์ JSON ขนาดใหญ่ แจกแจงโดยละเอียด
อย่าเอามันไปติดตั้งเพิ่มบนบริการที่ใช้ brotli หรือ gzip -9 อยู่แล้ว ผลตอบแทนลดลงเหลือ 9-11% ขณะที่ต้นทุน — การสูญเสียความอ่านง่ายถาวรเมื่อคุณ debug — ยังอยู่ ให้ตรวจแทนว่า gzip_types ครอบคลุม application/json หรือไม่ หลายไซต์เปิด gzip และบีบอัดเฉพาะ text/html เท่านั้น ทำให้ JSON ไม่ถูกบีบอัดเลย ในสถานการณ์นั้น minify ไม่ใช่ขั้นแรก การแก้คอนฟิกคือขั้นแรก
8. ตารางตัดสินใจ: ขั้นไหนก่อน
| สถานการณ์ของคุณ | ทำสิ่งนี้ก่อน | minify อยู่อันดับไหน |
|---|---|---|
| ไม่มีการบีบอัดเพื่อขนส่งเลย | ตั้งค่า gzip_types ใน Nginx หรือเปิด auto-compression ของ CDN |
ข้ามไป เก้าในสิบของกำไรระเหย |
| ใช้ gzip -1 (ค่าเริ่มต้น Nginx) | เพิ่ม gzip_comp_level เป็น 6 |
ที่สอง คุ้ม 21% |
| ใช้ brotli หรือ gzip -9 อยู่แล้ว | ตรวจคีย์ยาว เพิ่ม pagination หรือตัดฟิลด์ | ข้ามไป เหลือเพียง 9-11% |
| ชน Lambda 6 MB หรือ Firestore 1 MiB | minify โดยตรง 46% เต็ม ๆ นับ | ที่หนึ่ง |
| POST body, webhook, MQTT | minify โดยตรง การขนส่งแทบไม่เกี่ยวตรงนี้ | ที่หนึ่ง |
| ไฟล์คอนฟิกที่จะเข้า Git | คงไว้แบบ pretty | เฉพาะใน build output |
| Log, telemetry, dump แบบออฟไลน์ | ตัดอาร์กิวเมนต์ null, 2 ใน logger |
นั่น คือ ขั้นแรก |
กฎหนึ่งประโยค: ดูว่าคุณกำลังพยายามลดบัญชีไบต์ไหน — บัญชีที่บันทึกในเครื่อง (ดิสก์ โควตา ขีดจำกัดแพลตฟอร์ม request body) หรือบัญชีที่มีอยู่บนสายเท่านั้น ในเครื่องก่อนหมายถึง minify; บนสายเท่านั้นหมายถึงเปิด brotli หรือ gzip ก่อน
ในทางปฏิบัติ ให้รันลูป curl ข้างบนเพื่อยืนยันว่าการบีบอัดเพื่อขนส่งทำงานอยู่ แล้วส่งตัวอย่างผ่าน เครื่องมือ JSON Minify และอ่านตัวเลขการประหยัด หากตัวเลขนั้นสูงกว่า 40% ขณะที่ curl รายงาน identity และ gzip ขนาดใกล้กันมาก คอขวดของคุณคือคอนฟิกเซิร์ฟเวอร์ ไม่ใช่ JSON หากตัวเลข curl สองค่าต่างกันแล้ว เอกสารนี้เหลืออะไรให้น้อย และคุณควรตัดฟิลด์หรือทำ pagination แทน — หัวข้อของ สาระสำคัญในการออกแบบ JSON API Contract
JSON ที่ minify แล้วยังเป็น JSON ที่ถูกต้องหรือไม่?
ใช่ minify ตัดเฉพาะช่องว่างที่ RFC 8259 อนุญาตรอบอักขระเชิงโครงสร้างและไม่แตะเนื้อหาสตริงเลย ดังนั้น JSON.parse ให้ค่าที่เหมือนต้นฉบับ สิ่งเดียวที่เสียไปคือความอ่านง่ายของมนุษย์
brotli หรือ gzip?
บนตัวอย่าง minified เดียวกัน brotli ประหยัด 96.9% และ gzip -6 ประหยัด 95.4% — ช่องว่างแคบ ใช้ gzip -6 สำหรับ dynamic response เพื่อประหยัด CPU และสงวน brotli สำหรับสินทรัพย์ static ที่ส่งผ่าน HTTPS ซึ่งคุณสามารถ pre-compress เป็นไฟล์ .br ได้
ฉัน minify JSON แล้วแต่ API ไม่เร็วขึ้น ทำไม?
ตรวจ response ด้วย curl -sI ดู header Content-Encoding: gzip การตั้งค่า Nginx หลายแห่งกำหนด gzip_types เป็น text/html เท่านั้น ดังนั้น JSON ไม่เคยถูกครอบคลุม — และน้อยกว่าหนึ่งในห้าของ 46% ของคุณเดินทางถึงสายจริง
ควร commit ไฟล์คอนฟิกแบบ minified หรือไม่?
ไม่ควร เครื่องมือ diff เปรียบเทียบทีละบรรทัด ดังนั้น JSON บรรทัดเดียวทำให้ทุกการแก้ไขกลายเป็น "ทั้งบรรทัดเปลี่ยน" และการแก้ conflict แพงกว่าไบต์ที่คุณประหยัดมาก เก็บฉบับ pretty ใน repository และ minify ตอน build
response ต้องใหญ่แค่ไหนก่อน gzip จึงคุ้ม?
เกณฑ์ปกติคือ 256 ไบต์ถึง 1 KB response เล็ก ๆ อย่าง {"ok": true} — 16 ไบต์พร้อมการย่อหน้า — โตเป็น 36 ไบต์ใต้ gzip -6 เพราะ dictionary และ header มีต้นทุนมากกว่าที่มันกู้คืน นั่นคือสิ่งที่ gzip_min_length ควบคุมอย่างแม่นยำ