Giảm thiểu và nén tải trọng mạng bằng brotli

Michael DiBlasio
Michael DiBlasio

Lớp học lập trình này là phần mở rộng của tính năng Rút gọn và nén tải trọng mạng lớp học lập trình và giả định rằng bạn đã quen thuộc với các khái niệm cơ bản về nén. Như so với các thuật toán nén khác như gzip. Lớp học lập trình này sẽ khám phá cách Việc nén Brotli có thể giúp giảm hơn nữa tỷ lệ nén và hiệu suất tổng thể của ứng dụng kích thước.

Ảnh chụp màn hình ứng dụng

Đo

Trước khi đi sâu vào thêm cách tối ưu hoá, bạn nên phân tích trước trạng thái hiện tại của ứng dụng.

  1. Nhấp vào Phối lại để chỉnh sửa để có thể chỉnh sửa dự án.
  2. Để xem trước trang web, hãy nhấn vào Xem ứng dụng. Sau đó nhấn Toàn màn hình toàn màn hình.

Trong phần Rút gọn và nén tải trọng mạng trước đây lớp học lập trình, chúng tôi đã giảm kích thước main.js từ 225 KB xuống còn 61,6 KB. Trong lớp học lập trình này, bạn sẽ khám phá cách nén Brotli có thể giảm kích thước gói này hơn nữa.

Nén Brotli

Brotli là một thuật toán nén mới hơn có thể nén văn bản tốt hơn kết quả hơn gzip. Theo CertSimple, hiệu suất của Brotli là:

  • Nhỏ hơn 14% so với gzip đối với JavaScript
  • Nhỏ hơn 21% so với gzip đối với HTML
  • Ít hơn 17% so với gzip đối với CSS

Để sử dụng Brotli, máy chủ của bạn phải hỗ trợ HTTPS. Brotli được hỗ trợ trong phiên bản mới nhất của hầu hết các trình duyệt. Trình duyệt hỗ trợ Brotli sẽ đưa br vào tiêu đề Accept-Encoding:

Accept-Encoding: gzip, deflate, br

Bạn có thể xác định thuật toán nén nào được dùng thông qua Content-Encoding trong tab Mạng công cụ dành cho nhà phát triển Chrome (Command+Option+I hoặc Ctrl+Alt+I):

Bảng điều khiển mạng

Bật Brotli

Nén động

Tính năng nén động giúp nén tài sản một cách nhanh chóng khi chúng nhận mà trình duyệt yêu cầu.

Ưu điểm

  • Bạn không cần phải tạo và cập nhật các phiên bản nén đã lưu của tài sản xong.
  • Tính năng nén nhanh hoạt động đặc biệt hiệu quả đối với các trang web được tạo động.

Nhược điểm

  • Nén tệp ở mức cao hơn để đạt được tỷ lệ nén tốt hơn lâu hơn. Điều này có thể dẫn đến lượt truy cập hiệu suất khi người dùng chờ nội dung nén trước khi chúng được gửi bởi máy chủ.

Nén động bằng Node/Express

Tệp server.js chịu trách nhiệm thiết lập máy chủ Nút lưu trữ ứng dụng.

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);
});

Hiện tại, bạn chỉ cần nhập express và sử dụng express.static phần mềm trung gian để tải tất cả các tệp HTML, JS và CSS tĩnh trong public/directory (và các tệp đó do webpack tạo ra với mỗi bản dựng).

Để đảm bảo tất cả các thành phần đều được nén bằng brotli mỗi khi chúng được đã yêu cầu, shrink-ray mô-đun có thể sử dụng. Bắt đầu bằng cách thêm dưới dạng devDependency trong package.json:

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

Sau đó, nhập tệp này vào tệp máy chủ server.js:

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

Và thêm phần mềm này làm phần mềm trung gian trước khi express.static được gắn kết:

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

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

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

Bây giờ, hãy tải lại ứng dụng và xem kích thước gói trong bảng điều khiển Mạng:

Kích thước gói với tính năng nén Brotli động

Bạn hiện có thể thấy brotli được áp dụng từ bz trong tiêu đề Content-Encoding. main.bundle.js giảm từ 225 KB xuống còn 53,1 KB! Kích thước này nhỏ hơn khoảng 14% so với gzip (61,6 KB).

Nén tĩnh

Ý tưởng đằng sau phương pháp nén tĩnh là nén và lưu trước các thành phần thời gian.

Ưu điểm

  • Độ trễ do mức nén cao không còn là vấn đề đáng lo ngại. Không tùy chọn nào cần diễn ra một cách nhanh chóng để nén các tệp vì giờ đây chúng có thể được tìm nạp trực tiếp.

Nhược điểm

  • Các thành phần cần được nén trong mỗi bản dựng. Thời gian xây dựng có thể tăng lên đáng kể nếu sử dụng mức độ nén cao.

Nén tĩnh bằng Nút/Express và webpack

nén tĩnh liên quan đến việc nén các tệp trước, nên webpack có thể sửa đổi được chế độ cài đặt để nén nội dung trong bước tạo. Chiến lược phát hành đĩa đơn Bạn có thể sử dụng brotli-webpack-plugin để thực hiện việc này.

Bắt đầu bằng cách thêm dưới dạng devDependency trong package.json:

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

Giống như mọi trình bổ trợ webpack khác, hãy nhập trình bổ trợ này vào tệp cấu hình, webpack.config.js:

var path = require("path");

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

Và đưa mã này vào mảng trình bổ trợ:

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

Mảng trình bổ trợ sử dụng các đối số sau:

  • asset: Tên thành phần mục tiêu.
  • [file] được thay thế bằng tên tệp tài sản ban đầu.
  • test: Tất cả nội dung khớp với RegExp này (tức là các nội dung JavaScript kết thúc bằng .js).

Ví dụ: main.js sẽ được đổi tên thành main.js.br.

Khi ứng dụng tải lại và tạo lại, phiên bản nén của gói chính sẽ hiện đã được tạo. Mở Glitch Console để xem nội dung của trận đấu cuối cùng Thư mục public/ do máy chủ Nút phân phát.

  1. Nhấp vào nút Tools (Công cụ).
  2. Nhấp vào nút Bảng điều khiển.
  3. Trong bảng điều khiển, hãy chạy các lệnh sau để thay đổi thành public và xem tất cả các tệp trong thư mục đó:
cd public
ls -lh
Kích thước gói với tính năng nén Brotli tĩnh

Phiên bản nén brotli của gói (main.bundle.js.br) hiện đã được lưu ở đây và có kích thước nhỏ hơn ~76% (225 KB so với 53 KB) so với main.bundle.js.

Tiếp theo, hãy yêu cầu máy chủ gửi các tệp được nén bằng công nghệ brotli này bất cứ khi nào đang yêu cầu phiên bản JS gốc. Có thể thực hiện việc này bằng cách xác định trong server.js trước khi các tệp được phân phát bằng 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 dùng để cho máy chủ biết cách phản hồi yêu cầu GET đối với một điểm cuối cụ thể. Sau đó, hàm callback được dùng để xác định cách xử lý trường hợp này của bạn. Tuyến đường hoạt động như sau:

  • Việc chỉ định '*.js' làm đối số đầu tiên có nghĩa là đối số này sẽ hoạt động với mỗi điểm cuối được kích hoạt để tìm nạp tệp JS.
  • Trong lệnh gọi lại, .br được đính kèm vào URL của yêu cầu và Tiêu đề phản hồi Content-Encoding đã được đặt thành br.
  • Tiêu đề Content-Type được đặt thành application/javascript; charset=UTF-8 thành chỉ định loại MIME.
  • Cuối cùng, next() đảm bảo rằng trình tự tiếp tục với bất kỳ lệnh gọi lại nào có thể ở vị trí tiếp theo.

Do một số trình duyệt có thể không hỗ trợ nén brotli, hãy xác nhận brotli là được hỗ trợ trước khi trả về tệp được nén bằng brotli bằng cách kiểm tra Tiêu đề của yêu cầu Accept-Encoding bao gồm 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'));

Sau khi ứng dụng tải lại, hãy xem bảng điều khiển Mạng một lần nữa.

Kích thước gói 53,1 KB (từ 225KB)

Thành công! Bạn đã sử dụng tính năng nén Brotli để nén tài sản hơn nữa!

Kết luận

Lớp học lập trình này minh hoạ cách brotli có thể giảm thiểu đáng kể hiệu suất tổng thể của ứng dụng kích thước. Nếu được hỗ trợ, brotli sẽ là thuật toán nén mạnh hơn so với gzip