Давайте вместе сжимаемся и узнаем, как Brotli может помочь нам повысить производительность наших веб-сайтов. Я реализовал это в одном из своих рабочих проектов. Так что я просто подумал поделиться своим опытом со всеми.

Основные определения 📖

  1. Express: быстрый, незамысловатый, минималистичный веб-фреймворк для Node.js.
  2. Brotli: Это библиотека сжатия данных с открытым исходным кодом, разработанная Юрки Алакуйяла и Золтаном Сабадкой. Он основан на современном варианте алгоритма LZ77, кодировании Хаффмана и контекстном моделировании 2-го порядка.
  3. Webpack: это сборщик модулей. Он принимает модули с зависимостями и генерирует статические активы, представляющие эти модули.

Начнем с настоящего дерьма !!!

Было два способа реализовать сжатие в Express напрямую (без какого-либо веб-сервера, например, nginx и т. Д.):

  1. Статическое построение сжатых файлов с помощью Webpack (любого другого средства запуска или построения задач внешнего интерфейса) и их обслуживание по требованию клиента.
  2. Динамическое построение сжатых файлов во время выполнения (вы можете использовать require (« сжатие )») в express, чтобы динамически сжимать файлы и передавать их клиенту на лету.

Я реализовал только статическое построение файлов. Давайте поговорим об этом подробнее.

Статическое сжатие в Express

На первом этапе, при создании ваших пакетов, вы можете включить эти два плагина: сжатие-webpack-plugin ` и « плагин brotli-webpack `.

const CompressionPlugin = require(‘compression-webpack-plugin’);
const BrotliPlugin = require(‘brotli-webpack-plugin’);
module.exports = {
plugins: [
 new CompressionPlugin({
 asset: ‘[path].gz[query]’,
 algorithm: ‘gzip’,
 test: /\.js$|\.css$|\.html$/,
 threshold: 10240,
 minRatio: 0.8
 }),
 new BrotliPlugin({
 asset: ‘[path].br[query]’,
 test: /\.js$|\.css$|\.html$/,
 threshold: 10240,
 minRatio: 0.8
 })
]
}

Эти плагины будут генерировать файлы gzip и brotli для всех ваших пакетов, т.е. если пакет называется vendor_d0cfe49e718c1366c661.js, вы получите vendor_d0cfe49e718c1366c661.js.gzip и vendor_d0cfe49e718c1366c661. strongjs.br в том же каталоге (предположим, что это тот же каталог) > / dist / static / vendor_d0cfe49e718c1366c661.js. * на данный момент).

PS: Приведенный выше код будет генерировать файлы .gzip и .br только в том случае, если minRatio 0,8 достигается при сжатии файлов. Таким образом, в случае очень маленьких файлов файлы gzip и br не будут сгенерированы. Причина в том, что время сжатия и распаковки обходится дороже, чем фактический файл, обслуживаемый без сжатия.

Вам также может потребоваться установить для общедоступного пути в выходной конфигурации webpack значение «/ static». Он будет указывать общедоступный URL-адрес выходных файлов при ссылке в браузере. Это поможет нам фильтровать URL-адрес запроса и обслуживать файлы с помощью express-static-gzip только static, если URL-адрес состоит из «/ static».

output: {
path: '/dist/static',
filename: ‘[name]_[chunkhash].js’,
chunkFilename: ‘[id].[chunkhash].js’,
publicPath: ‘/static/’,
},

На втором этапе, который заключается в обслуживании нужного файла на основе входных заголовков из клиентского браузера. Мы будем использовать express-static-gzip

var express = require(“express”);
var expressStaticGzip = require(“express-static-gzip”);
var app = express();
// app.use(express.static(path.join(__dirname))); This was used previously with express.
app.use(“/”, expressStaticGzip(path.join(__dirname), {
 enableBrotli: true
}));

Приведенный выше код является настройкой кода по умолчанию из «express-static-gzip», но я хотел обслуживать только статические файлы из этой библиотеки. Если файл не существует, я хотел выдать ошибку, и мой код не должен идти дальше по другим маршрутам. Итак, я немного взломал исходный код и создал новый файл промежуточного программного обеспечения compress.js.

Ниже взломанный код:

var express = require(“express”);
const expressStaticGzip = require(‘compression’); // compression.js gist is available on the github.
var app = express();
 
app.get('*', expressStaticGzip(path.join(__dirname), {
 urlContains: ‘static/’,
 fallthrough: false,
 enableBrotli: true,
}));

Я использовал здесь три параметра

  1. urlContains: он проверит, содержит ли исходный URL-адрес запроса "static /". Тогда обслуживайте файлы только через этот плагин, иначе URL-адрес игнорируется.
  2. fallthrough: ошибка должна быть ложной, если файл, который вы ищете, не существует в каталоге path.join (__ dirname), а URL-адрес содержит urlContains.
  3. enableBrotli: он проверит, доступен ли файл Brotli в path.join (__ dirname) и соответствующие заголовки запрашиваются клиентом, а затем обслужит файл .br.

Ниже приводится суть сжатия.js. Я взломал строки 59-65.

Анализ результатов:

Давайте сравним производительность веб-сайта с Brotli или GZip или просто с несжатыми миниатюрными файлами.

В Бога мы верим, все другие приносят данные. -W. Эдвардс Деминг

Давайте углубимся в анализ и найдем действительные числа. Так как это сайт моего рабочего места, который мы использовали для внутренних целей. Я не могу предоставить настоящий снимок экрана здесь, но ниже приведены реальные цифры, которые я собрал при тестировании веб-сайта на различных типах сжатия.

  1. Brotli на ~ 8% ((7.24–6.67) / 7.24) эффективнее, чем GZIP, и на 65.7% (((19.48–6.67) / 19.48) эффективнее, чем несжатый файл. Если браузер не сможет обслуживать Brotli, у нас есть запасной вариант для gzip, который на 62% ((19,48–7,24) / 19,48) эффективнее несжатого файла. Итак, здесь мы имеем ситуацию Win Win.
  2. А теперь проанализируем размер. Brotli на ((586–458) / 586) ~ 21,85% эффективен, чем GZIP, и ((2,5 * 1024–458) /2,5 * 1024) ~ 82,1% эффективен, чем несжатые файлы. Так много пропускной способности можно сэкономить, используя сжатие Brotli.

Некоторые данные для медленной сети 3G:

Спасибо всем за то, что дочитали до сих пор. Если вам это нравится и вы хотите, чтобы я написал больше, нажмите 💚, чтобы побудить меня.

PS: Спасибо Kuldeep за помощь в устранении некоторых пробелов и за помощь в устранении сбоев в процессе.