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

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

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

วัดระยะทาง

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

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

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

การบีบอัด 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

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

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

ข้อดี

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

ข้อเสีย

  • การบีบอัดไฟล์ที่มีระดับสูงขึ้นเพื่อให้ได้อัตราส่วนการบีบอัดที่ดีขึ้นใช้เวลา นานขึ้น กรณีนี้อาจทำให้เกิด Performance 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 ในทุกบิลด์)

เพื่อให้แน่ใจว่าได้บีบอัดเนื้อหาทั้งหมดโดยใช้ Brotli ทุกครั้ง shrink-ray มาใช้ได้ เริ่มต้นด้วยการเพิ่มเป็น 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() จะตรวจสอบว่าลำดับต่อเนื่องไปยัง Callback ที่อาจ เป็นรายการถัดไป

เนื่องจากบางเบราว์เซอร์อาจไม่สนับสนุนการบีบอัดโบรตลี (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