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

Измерить
Прежде чем добавлять оптимизации, всегда полезно сначала проанализировать текущее состояние приложения.
- Нажмите Создать ремикс, чтобы сделать проект редактируемым.
- Чтобы посмотреть сайт, нажмите 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):
Как включить 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'));
Теперь перезагрузите приложение и посмотрите на размер пакета на панели "Сеть":
Теперь в заголовке 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.
- Нажмите кнопку Инструменты.
- Нажмите кнопку Консоль.
- В консоли выполните следующие команды, чтобы перейти в каталог
publicи посмотреть все его файлы:
cd public
ls -lh
Сжатая с помощью 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'));
После перезагрузки приложения снова посмотрите на панель "Сеть".
Готово! Вы использовали сжатие Brotli, чтобы дополнительно сжать объекты.
Заключение
В этой практической работе мы рассказали, как brotli может уменьшить размер приложения. brotli – более мощный алгоритм сжатия, чем gzip.