Минимизируйте и сжимайте полезную нагрузку сети с помощью 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 .