Эта лабораторная работа является продолжением лабораторной работы «Минимизация и сжатие сетевых данных» и предполагает, что вы знакомы с основами сжатия. В этой лабораторной работе рассматривается, как сжатие Brotli ( br
) может дополнительно снизить степень сжатия и общий размер вашего приложения по сравнению с другими алгоритмами сжатия, такими как gzip
.
Мера
Прежде чем приступать к оптимизации, всегда полезно проанализировать текущее состояние приложения.
- Нажмите «Ремикс для редактирования», чтобы сделать проект редактируемым.
- Для предварительного просмотра сайта нажмите «Просмотреть приложение» . Затем нажмите «Полный экран».
.
В предыдущей лабораторной работе «Минимизация и сжатие сетевых полезных данных» мы уменьшили размер файла 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
):

Как включить 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
применяется из bz
в заголовке Content-Encoding
. Размер 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
: обрабатываются все ресурсы, соответствующие этому RegExp (то есть ресурсы 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
.
Затем укажите серверу отправлять эти файлы, сжатые с помощью brotli, при каждом запросе их исходных 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, убедитесь, что brotli поддерживается, прежде чем возвращать сжатый 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
.