ลดขนาดและบีบอัดเพย์โหลดของเครือข่ายด้วย Brotli

โค้ดแล็บนี้เป็นส่วนขยายของโค้ดแล็บสำหรับย่อขนาดและบีบอัดเพย์โหลดของเครือข่าย และถือว่าคุณคุ้นเคยกับแนวคิดพื้นฐานของการบีบอัด เมื่อเทียบกับอัลกอริทึมการบีบอัดอื่นๆ เช่น gzip โค้ดแล็บนี้จะอธิบายวิธีที่การบีบอัด Brotli (br) สามารถลดอัตราส่วนการบีบอัดและขนาดโดยรวมของแอปได้

ภาพหน้าจอแอป

วัดระยะทาง

ก่อนเพิ่มการเพิ่มประสิทธิภาพ คุณควรวิเคราะห์สถานะปัจจุบันของแอปพลิเคชันก่อน

  1. คลิกรีมิกซ์เพื่อแก้ไขเพื่อให้โปรเจ็กต์แก้ไขได้
  2. หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ เต็มหน้าจอ

ในการลดขนาดและบีบอัดเพย์โหลดของเครือข่าย codelab ก่อนหน้านี้ เราลดขนาดของ main.js จาก 225 KB เหลือ 61.6 KB ในโค้ดแล็บนี้ คุณจะได้ดูว่าการบีบอัด Brotli สามารถลดขนาด App Bundle นี้ได้อย่างไร

การบีบอัด Brotli

Brotli เป็นอัลกอริทึมการบีบอัดที่ใหม่กว่าซึ่งให้ผลลัพธ์การบีบอัดข้อความที่ดีกว่า gzip ประสิทธิภาพของ Brotli ตามที่ CertSimple ระบุไว้มีดังนี้

  • เล็กกว่า gzip สำหรับ JavaScript 14%
  • เล็กกว่า gzip สำหรับ HTML 21%
  • เล็กกว่า gzip สำหรับ CSS อยู่ 17%

หากต้องการใช้ Brotli เซิร์ฟเวอร์ของคุณต้องรองรับ HTTPS เบราว์เซอร์สมัยใหม่ทั้งหมดรองรับ Brotli เบราว์เซอร์ที่รองรับ Brotli จะใส่ br ไว้ในส่วนหัว Accept-Encoding

Accept-Encoding: gzip, deflate, br

คุณระบุอัลกอริทึมการบีบอัดที่ใช้ได้โดยใช้ช่อง Content-Encoding ในแท็บเครือข่ายของเครื่องมือสําหรับนักพัฒนาซอฟต์แวร์ Chrome (Command+Option+I หรือ Ctrl+Alt+I)

แผงเครือข่าย คอลัมน์การเข้ารหัสเนื้อหาจะแสดงการเข้ารหัสที่ใช้กับชิ้นงานต่างๆ ซึ่งรวมถึง gzip และ brotli (br)

วิธีเปิดใช้ Brotli

วิธีการตั้งค่าเว็บเซิร์ฟเวอร์ให้ส่งทรัพยากรที่เข้ารหัส Brotli จะขึ้นอยู่กับวิธีคุณวางแผนที่จะเข้ารหัส ตัวเลือกของคุณคือบีบอัดทรัพยากรแบบไดนามิกด้วย Brotli ณ เวลาที่มีคำขอ (แบบไดนามิก) หรือเข้ารหัสทรัพยากรล่วงหน้าเพื่อให้มีการบีบอัดแล้วเมื่อผู้ใช้ขอ (แบบคงที่)

การบีบอัดแบบไดนามิก

การบีบอัดแบบไดนามิกเกี่ยวข้องกับการบีบอัดชิ้นงานขณะที่เบราว์เซอร์ขอ

ข้อดี

  • คุณไม่จำเป็นต้องสร้างและอัปเดตชิ้นงานเวอร์ชันที่บีบอัดไว้
  • การบีบอัดขณะใช้งานเหมาะอย่างยิ่งสําหรับหน้าเว็บที่สร้างขึ้นแบบไดนามิก

ข้อเสีย

  • การบีบอัดไฟล์ในระดับที่สูงขึ้นเพื่อให้ได้อัตราส่วนการบีบอัดที่ดีขึ้นจะใช้เวลานานขึ้น ซึ่งอาจส่งผลเสียต่อประสิทธิภาพเนื่องจากผู้ใช้ต้องรอให้เซิร์ฟเวอร์บีบอัดชิ้นงานก่อนที่จะส่ง

การบีบอัดแบบไดนามิกด้วย Node และ Express

ไฟล์ server.js มีหน้าที่รับผิดชอบในการตั้งค่าเซิร์ฟเวอร์ Node ที่โฮสต์แอปพลิเคชัน

const express = require('express');
const app = express();
app.use(express.static('public'));

const listener = app.listen(process.env.PORT, function() {
  console.log(`Your app is listening on port ${listener.address().port}`);
});

ทั้งหมดนี้ทําเพื่อนําเข้า express และใช้ express.static มิดเดิลแวร์เพื่อโหลดไฟล์ HTML, JS และ CSS แบบคงที่ทั้งหมดใน public/directory (และไฟล์เหล่านั้นสร้างขึ้นโดย webpack กับทุกบิลด์)

คุณสามารถใช้โมดูล shrink-ray เพื่อให้แน่ใจว่าระบบจะบีบอัดชิ้นงานทั้งหมดโดยใช้ Brotli ทุกครั้งที่มีการขอ เริ่มต้นด้วยการเพิ่มเป็น devDependency ใน package.json โดยทำดังนี้

"devDependencies": {
  // ...
  "shrink-ray": "^0.1.3"
},

และนําเข้าลงในไฟล์เซิร์ฟเวอร์ server.js โดยทําดังนี้

const express = require('express');
const shrinkRay = require('shrink-ray');

และเพิ่มเป็นมิดเดิลแวร์ก่อนที่จะติดตั้ง express.static

// ...
const app = express();

// Compress all requests
app.use(shrinkRay());
app.use(express.static('public'));

ตอนนี้ให้โหลดแอปซ้ำ แล้วดูขนาด App Bundle ในแผงเครือข่าย

ขนาดกลุ่มที่มีการบีบอัด Brotli แบบไดนามิก

ตอนนี้คุณจะเห็น brotli มีผลบังคับใช้จาก bz ในส่วนหัว Content-Encoding main.bundle.js ลดลงจาก 225 KB เป็น 53.1 KB ซึ่งเล็กกว่าgzip (61.6 KB) ประมาณ 14%

การบีบอัดแบบคงที่

แนวคิดเบื้องหลังการบีบอัดแบบคงที่คือการบีบอัดและบันทึกชิ้นงานล่วงหน้า

ข้อดี

  • คุณจึงไม่ต้องกังวลเรื่องเวลาในการตอบสนองเนื่องจากระดับการบีบอัดสูงอีกต่อไป คุณไม่ต้องดำเนินการใดๆ ขณะบีบอัดไฟล์ เนื่องจากตอนนี้ระบบสามารถดึงข้อมูลไฟล์ได้โดยตรง

ข้อเสีย

  • ชิ้นงานต้องได้รับการบีบอัดกับทุกบิลด์ เวลาสร้างอาจเพิ่มขึ้นอย่างมากหากใช้การบีบอัดระดับสูง

การบีบอัดแบบคงที่ด้วย Node และ Express ด้วย webpack

เนื่องจากการบีบอัดแบบคงที่เกี่ยวข้องกับการบีบอัดไฟล์ล่วงหน้า คุณจึงแก้ไขการตั้งค่า webpack เพื่อบีบอัดชิ้นงานเป็นส่วนหนึ่งของขั้นตอนการสร้างได้ คุณใช้ brotli-webpack-plugin กับการดำเนินการนี้ได้

เริ่มต้นด้วยการเพิ่มเป็น devDependency ใน package.json โดยทำดังนี้

"devDependencies": {
  // ...
 "brotli-webpack-plugin": "^1.1.0"
},

นำเข้าในไฟล์การกําหนดค่า เช่นเดียวกับปลั๊กอิน webpack อื่นๆ ดังนี้ webpack.config.js

var path = require("path");

//...
var BrotliPlugin = require('brotli-webpack-plugin');

และใส่ไว้ในอาร์เรย์ปลั๊กอิน

module.exports = {
  // ...
  plugins: [
    // ...
    new BrotliPlugin({
      asset: '[file].br',
      test: /\.(js)$/
    })
  ]
},

อาร์เรย์ปลั๊กอินใช้อาร์กิวเมนต์ต่อไปนี้

  • asset: ชื่อชิ้นงานเป้าหมาย
  • [file] จะแทนที่ด้วยชื่อไฟล์ชิ้นงานเดิม
  • test: ระบบจะประมวลผลชิ้นงานทั้งหมดที่ตรงกับนิพจน์ทั่วไปนี้ (นั่นคือ ชิ้นงาน JavaScript ที่ลงท้ายด้วย .js)

เช่น main.js จะเปลี่ยนชื่อเป็น main.js.br

เมื่อแอปโหลดซ้ำและสร้างใหม่ ระบบจะสร้างแพ็กเกจหลักเวอร์ชันที่บีบอัดแล้ว เปิด Glitch Console เพื่อดูสิ่งที่อยู่ในไดเรกทอรี public/ สุดท้ายที่เซิร์ฟเวอร์ Node แสดง

  1. คลิกปุ่มเครื่องมือ
  2. คลิกปุ่มคอนโซล
  3. ในคอนโซล ให้เรียกใช้คําสั่งต่อไปนี้เพื่อเปลี่ยนเป็นไดเรกทอรี public และดูไฟล์ทั้งหมดในไดเรกทอรี
cd public
ls -lh
ขนาด Bundle ที่มีการบีบอัด Brotli แบบคงที่

ตอนนี้ระบบได้บันทึกmain.bundle.js.brเวอร์ชันที่บีบอัดด้วย Brotli ไว้ที่นี่ด้วยแล้ว และมีขนาดเล็กลงประมาณ 76% (225 KB เทียบกับ 53 KB) กว่าmain.bundle.js

ถัดไป ให้บอกเซิร์ฟเวอร์ให้ส่งไฟล์ที่บีบอัดด้วย Brotli เหล่านี้ทุกครั้งที่มีการขอ JS เวอร์ชันเดิม ซึ่งทำได้โดยการกำหนดเส้นทางใหม่ใน server.js ก่อนที่ระบบจะแสดงไฟล์ด้วย express.static

const express = require('express');
const app = express();

app.get('*.js', (req, res, next) => {
  req.url = req.url + '.br';
  res.set('Content-Encoding', 'br');
  res.set('Content-Type', 'application/javascript; charset=UTF-8');
  next();
});

app.use(express.static('public'));

app.get ใช้เพื่อบอกเซิร์ฟเวอร์ว่าจะตอบกลับคําขอ GET สําหรับอุปกรณ์ปลายทางที่เฉพาะเจาะจงอย่างไร จากนั้นระบบจะใช้ฟังก์ชัน Callback เพื่อกำหนดวิธีจัดการคำขอนี้ เส้นทางจะทํางานดังนี้

  • การระบุ '*.js' เป็นอาร์กิวเมนต์แรกหมายความว่าการดำเนินการนี้จะใช้ได้กับทุกปลายทางที่เรียกให้แสดงเพื่อดึงข้อมูลไฟล์ JS
  • ภายในการเรียกกลับ ระบบจะแนบ .br กับ URL ของคำขอ และตั้งค่าส่วนหัวของคำตอบ Content-Encoding เป็น br
  • ตั้งค่าส่วนหัว Content-Type เป็น application/javascript; charset=UTF-8 เพื่อระบุประเภท MIME
  • สุดท้าย next() จะตรวจสอบว่าลําดับจะดําเนินการต่อไปยังการเรียกกลับที่อาจเกิดขึ้นถัดไป

เนื่องจากเบราว์เซอร์บางรุ่นอาจไม่รองรับการบีบอัด Brotli ให้ตรวจสอบว่าระบบรองรับ Brotli หรือไม่ก่อนที่จะส่งไฟล์ที่บีบอัดด้วย Brotli โดยตรวจสอบว่าAccept-Encodingส่วนหัวคำขอมีbrรายการต่อไปนี้

const express = require('express');
const app = express();

app.get('*.js', (req, res, next) => {
  if (req.header('Accept-Encoding').includes('br')) {
    req.url = req.url + '.br';
    console.log(req.header('Accept-Encoding'));
    res.set('Content-Encoding', 'br');
    res.set('Content-Type', 'application/javascript; charset=UTF-8');
  }

  next();
});

app.use(express.static('public'));

เมื่อแอปโหลดซ้ำแล้ว ให้ดูที่แผงเครือข่ายอีกครั้ง

ขนาดกลุ่ม 53.1 KB (จาก 225 KB)

สำเร็จ! คุณใช้การบีบอัด Brotli เพื่อบีบอัดชิ้นงานเพิ่มเติมแล้ว

บทสรุป

โค้ดแล็บนี้แสดงให้เห็นว่า brotli ช่วยลดขนาดโดยรวมของแอปได้อย่างไร brotli เป็นอัลกอริทึมการบีบอัดที่มีประสิทธิภาพมากกว่า gzip ในกรณีที่รองรับ