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

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

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

วัดระยะทาง

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

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

ใน Minify และบีบอัดข้อมูล Payload ของเครือข่ายก่อนหน้านี้ เราได้ลดขนาด main.js จาก 225 KB เป็น 61.6 KB ใน Codelab นี้ คุณจะได้ดูวิธีที่การบีบอัดของ Brotli ช่วยลดขนาด Bundle นี้ได้มากขึ้น

การบีบอัด Brotli

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

  • น้อยกว่า gzip 14% สำหรับ JavaScript
  • น้อยกว่า gzip 21% สำหรับ HTML
  • น้อยกว่า gzip 17% สำหรับ CSS

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

Accept-Encoding: gzip, deflate, br

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

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

การเปิดใช้งาน Brotli

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

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

ข้อดี

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

ข้อเสีย

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

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

ไฟล์ 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)

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

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

ข้อดี

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

ข้อเสีย

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

การบีบอัดแบบคงที่ด้วยโหนด/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 สำหรับปลายทางหนึ่งๆ จากนั้นระบบจะใช้ฟังก์ชันเรียกกลับเพื่อกำหนดวิธีจัดการคำขอนี้ เส้นทางมีการทำงานดังนี้

  • การระบุ '*.js' เป็นอาร์กิวเมนต์แรกหมายความว่าวิธีนี้ได้ผลกับทุกปลายทางที่เริ่มทำงานเพื่อดึงข้อมูลไฟล์ JS
  • ภายในโค้ดเรียกกลับ ระบบจะแนบ .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