Сжимать один и тот же файл каждый раз
Apache сжимает ответы на лету. Для страницы, которая каждый раз другая, это единственный путь. Для таблицы стилей, которая меняется раз в месяц, это значит, что сервер делает одну и ту же работу заново для каждого посетителя, неделями, и каждый раз выбрасывает результат. Кэша для этого нет.
Измерено 19 августа 2026 года по уже установленному соединению, на собственных style.css (124 кБ) и world.js (102 кБ) этого сайта:
| время | байт | |
| без сжатия | 2,9 мс | 124 755 |
| gzip, на лету | 18,1 мс | 34 995 |
| brotli, на лету | 14,5 мс | 32 685 |
| world.js, gzip | 47,9 мс | 38 283 |
| world.js, brotli | 15,9 мс | 38 086 |
Сорок восемь миллисекунд процессора на запрос ради результата, совпадающего байт в байт. На Raspberry Pi это не ошибка округления.
Сжать один раз, на диск
Шаг сборки кладёт сжатый файл рядом с исходным, а правило перезаписи отдаёт его, когда браузер сообщает, что принимает gzip. Отдать готовый файл стоит столько, сколько стоит отдать любой файл.
gzip, а не brotli, по скучной причине: на этой машине не установлена программа brotli. Файлы выходят примерно на 7 % больше, чем сделал бы brotli, а время сервера — пятая часть того, что стоит brotli на лету. Этот обмен стоило совершить сейчас, а не ждать более красивого ответа.
Версия стоит в имени файла
Сборка пишет style.css.<mtime>.gz, а ?v= в разметке — то же самое время изменения. Правило перезаписи срабатывает только тогда, когда файл с подходящим числом существует.
У этого устройства есть свойство, ради которого стоит проектировать нарочно: если изменить таблицу стилей и забыть пересобрать, число в разметке укажет на несуществующий файл, правило не сработает, и Apache обычным образом отдаст исходник. Худшее, что случится, — пропадёт ускорение. Устаревшая таблица стилей выйти не может. Любую схему кэширования стоит проверять этим вопросом — когда она ломается, становится медленно или становится неверно?
Ошибка посередине всего этого
Отдаваемый файл уже в gzip, значит на выходе его нельзя сжимать второй раз. В настройке сперва стояло no-gzip, и это останавливает один из двух сжимателей Apache. Второй, mod_brotli, бодро упаковывал готовый gzip-файл ещё раз в brotli, пока заголовок ответа продолжал утверждать gzip.
Браузеры получали нечитаемое содержимое. Заметили это не при взгляде на страницу — заметили при сложении байтов, где вышло число, не имеющее смысла. Нужны оба, no-gzip и no-brotli, и лишь один из них очевиден.