Минимизируйте и сжимайте полезную нагрузку сети с помощью brotli

Майкл ДиБлазио
Michael DiBlasio

Эта лаборатория является расширением лаборатории по минимизации и сжатию сетевых полезных данных и предполагает, что вы знакомы с основными концепциями сжатия. По сравнению с другими алгоритмами сжатия, такими как gzip , в этой лаборатории кода показано, как сжатие Brotli может еще больше уменьшить коэффициент сжатия и общий размер вашего приложения.

Скриншот приложения

Мера

Прежде чем приступить к оптимизации, всегда полезно сначала проанализировать текущее состояние приложения.

  1. Нажмите Remix to Edit , чтобы сделать проект доступным для редактирования.
  2. Чтобы просмотреть сайт, нажмите «Просмотреть приложение» . Затем нажмите Полноэкранный режим полноэкранный .

В предыдущей лаборатории по минимизации и сжатию сетевых полезных данных мы уменьшили размер main.js с 225 КБ до 61,6 КБ. В этой лаборатории вы узнаете, как сжатие Brotli может еще больше уменьшить размер этого пакета.

Компрессия Бротли

Brotli — это новый алгоритм сжатия, который может обеспечить даже лучшие результаты сжатия текста, чем gzip . Согласно CertSimple , производительность Brotli составляет:

  • На 14 % меньше, чем gzip для JavaScript.
  • На 21 % меньше, чем gzip для HTML.
  • На 17 % меньше, чем gzip для CSS.

Чтобы использовать Brotli, ваш сервер должен поддерживать HTTPS. Brotli поддерживается в последних версиях большинства браузеров . Браузеры, поддерживающие Brotli, будут включать br в заголовки Accept-Encoding :

Accept-Encoding: gzip, deflate, br

Вы можете определить, какой алгоритм сжатия используется, с помощью поля Content-Encoding на вкладке «Сеть инструментов разработчика Chrome» ( Command+Option+I или Ctrl+Alt+I ):

Сетевая панель

Включение Бротли

Динамическое сжатие

Динамическое сжатие предполагает сжатие ресурсов «на лету» по мере их запроса браузером.

Плюсы

  • Создавать и обновлять сохраненные сжатые версии ресурсов не требуется.
  • Сжатие «на лету» особенно хорошо работает для веб-страниц, которые генерируются динамически.

Минусы

  • Сжатие файлов на более высоких уровнях для достижения лучшей степени сжатия занимает больше времени. Это может привести к снижению производительности, поскольку пользователь ожидает сжатия ресурсов, прежде чем они будут отправлены сервером.

Динамическое сжатие с помощью Node/Express

Файл server.js отвечает за настройку сервера Node, на котором размещено приложение.

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 (и эти файлы создаются веб-пакетом при каждой сборке).

Чтобы убедиться, что все ресурсы сжимаются с использованием 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 КБ до 53,1 КБ ! Это примерно на 14% меньше по сравнению с gzip (61,6 КБ).

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

Идея статического сжатия заключается в предварительном сжатии и сохранении ресурсов.

Плюсы

  • Задержка из-за высокого уровня сжатия больше не является проблемой. Для сжатия файлов ничего не нужно делать «на лету», поскольку теперь их можно получить напрямую.

Минусы

  • Ресурсы необходимо сжимать при каждой сборке. Время сборки может значительно увеличиться, если используются высокие уровни сжатия.

Статическое сжатие с помощью Node/Express и веб-пакета

Поскольку статическое сжатие предполагает предварительное сжатие файлов, настройки веб-пакета можно изменить для сжатия ресурсов на этапе сборки. Для этого можно использовать плагин brotli-webpack-plugin .

Начните с добавления его как devDependency в package.json :

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

Как и любой другой плагин веб-пакета, импортируйте его в файл конфигурации 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 : обрабатываются все ресурсы, соответствующие этому RegExp (то есть ресурсы JavaScript, оканчивающиеся на .js ).

Например, main.js будет переименован в main.js.br

Когда приложение перезагружается и перестраивается, теперь создается сжатая версия основного пакета. Откройте консоль Glitch, чтобы посмотреть, что находится внутри последнего каталога public/ , обслуживаемого сервером Node.

  1. Нажмите кнопку «Инструменты» .
  2. Нажмите кнопку Консоль .
  3. В консоли выполните следующие команды, чтобы перейти в public каталог и просмотреть все его файлы:
cd public
ls -lh
Размер пакета со статическим сжатием Бротли

Версия пакета, сжатая Brotli, main.bundle.js.br , теперь также сохраняется здесь и имеет размер примерно на 76% меньше (225 КБ против 53 КБ), чем 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 КБ (было 225 КБ)

Успех! Вы использовали сжатие Brotli для дальнейшего сжатия своих ресурсов!

Заключение

В этой кодовой лаборатории показано, как brotli может еще больше уменьшить общий размер вашего приложения. Если поддерживается, brotli является более мощным алгоритмом сжатия, чем gzip .