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

Michael DiBlasio
Michael DiBlasio

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

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

Измерить

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

  1. Нажмите Создать ремикс, чтобы сделать проект редактируемым.
  2. Чтобы посмотреть сайт, нажмите View App (Посмотреть приложение), а затем – Fullscreen (Полноэкранный режим) полноэкранный режим.

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

Сжатие Brotli

Brotli – это более новый алгоритм, который может обеспечить ещё более эффективное сжатие текста, чем gzip. По данным CertSimple, Brotli обеспечивает:

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

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

Accept-Encoding: gzip, deflate, br

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

Панель "Сеть". В столбце Content-encoding (Кодировка контента) показаны кодировки, используемые для различных объектов, включая gzip и brotli (br).

Как включить Brotli

Способ настройки веб-сервера для отправки ресурсов, закодированных с помощью Brotli, зависит от того, как вы планируете их кодировать. Вы можете динамически сжимать ресурсы с помощью Brotli во время запроса или кодировать их заранее, чтобы они уже были сжаты к моменту запроса пользователя (статически).

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

Динамическое сжатие выполняется на лету, когда браузер запрашивает объекты.

Преимущества

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

Недостатки

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

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

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

const express = require('express');
const app = express();
app.use(express.static('public'));

const 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:

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

Добавьте его в качестве промежуточного ПО перед подключением express.static:

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

// Compress all requests
app.use(shrinkRay());
app.use(express.static('public'));

Теперь перезагрузите приложение и посмотрите на размер пакета на панели "Сеть":

Размер пакета с динамическим сжатием Brotli.

Теперь в заголовке Content-Encoding вы увидите, что brotli применяется из bz. main.bundle.js уменьшился с 225 до 53,1 КБ. Это примерно на 14 % меньше, чем у gzip (61,6 КБ).

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

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

Преимущества

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

Недостатки

  • Объекты нужно сжимать при каждой сборке. При использовании высоких уровней сжатия время сборки может значительно увеличиться.

Статическое сжатие с помощью 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.

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

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

Сжатая с помощью Brotli версия пакета main.bundle.js.br теперь также сохраняется здесь и примерно на 76 % меньше по размеру (225 КБ по сравнению с 53 КБ), чем main.bundle.js.

Затем настройте сервер так, чтобы он отправлял эти сжатые файлы каждый раз, когда запрашиваются их исходные JS-версии. Для этого нужно определить новый маршрут в server.js, прежде чем файлы будут переданы с помощью express.static.

const express = require('express');
const 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. Чтобы убедиться, что оно поддерживается, проверьте, содержит ли заголовок запроса Accept-Encoding значение br.

const express = require('express');
const 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.