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

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

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

วัดระยะทาง

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

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

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

การบีบอัด Brotli

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

  • น้อยกว่า gzip 14% สำหรับ JavaScript
  • มีขนาดเล็กกว่า gzip 21% สำหรับ HTML
  • น้อยกว่า gzip 17% สำหรับ CSS

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

Accept-Encoding: gzip, deflate, br

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

แผงเครือข่าย

การเปิดใช้ Brotli

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

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

ข้อดี

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

ข้อเสีย

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

การบีบอัดแบบไดนามิกด้วยโหนด/ด่วน

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

var express = require('express');

var app = express();

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

var 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:

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

และเพิ่มเป็นมิดเดิลแวร์ก่อนต่อเชื่อม express.static

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

// compress all requests
app.use(shrinkRay());

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

โหลดแอปซ้ำแล้วดูขนาดแพ็กเกจในแผงเครือข่าย

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

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

  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

var express = require('express');

var 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
  • ภายใน Callback จะมีการแนบ .br ไว้กับ URL ของคำขอและตั้งค่าส่วนหัวการตอบกลับ Content-Encoding เป็น br
  • ตั้งค่าส่วนหัว Content-Type เป็น application/javascript; charset=UTF-8 เพื่อระบุประเภท MIME
  • สุดท้าย next() จะดูแลให้ลำดับมีการเรียกกลับทั้งหมดซึ่งอาจเป็นลำดับถัดไป

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

var express = require('express');

var 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 เพื่อบีบอัดเนื้อหาเพิ่มเติม!

บทสรุป

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