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

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

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

วัดระยะทาง

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

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

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

การบีบอัด Brotli

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

  • น้อยกว่า gzip 14% สำหรับ JavaScript
  • มีขนาดเล็กกว่า gzip 21% สำหรับ HTML
  • เล็กกว่า 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 ณ เวลาที่มีคำขอ (แบบไดนามิก) หรือเข้ารหัสทรัพยากรล่วงหน้าเพื่อให้มีการบีบอัดแล้วเมื่อผู้ใช้ขอ (แบบคงที่)

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

การบีบอัดแบบไดนามิกเกี่ยวข้องกับการบีบอัดเนื้อหาแบบเรียลไทม์ตามที่เบราว์เซอร์ขอ

ข้อดี

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

ข้อเสีย

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

การบีบอัดแบบไดนามิกด้วย 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 ซึ่งเล็กกว่าประมาณ 14% เมื่อเทียบกับ gzip (61.6 KB)

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

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

ข้อดี

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

ข้อเสีย

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

การบีบอัดแบบคงที่ด้วย 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
ขนาดแพ็กเกจที่มีการบีบอัด 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