Compression dictionary transport



Как мы обычно доставляем ассеты пользователям? Ну, добавляем хешик на основе контента к названию файла. Юзер его скачивает. Потом меняем одну строчку, а юзер снова скачивает ассет целиком размером в 200кб.



А что если можно по другому?



Я недавно упомянал Brotli в контексте CI, но если посмотреть на сжатие в браузерах, то у нас не так много вариантов, а точнее два: Gzip постарше и Brotli помоложе и эффективней.



Одна из идей, которая бротли делает эффективней — статический словарь. Секрет в том, что есть некий стандартный набор строк, который встречается на каждом сайте: например type=“text/javascript” и используя общий словарь, мы экономим байты на передаче этой информации.



Но на деле общее пересечение среди всех сайтов небольшое, на одном текст/джаваскрипт далеко не уедешь.



Здесь то и начинается пост: а что если мы научим сервер отправлять только дифф для ассетов?



Идея выглядит так:

1. Пользователь заходит на сайт и браузер делает запрос за ассетом static.example.com/app/main.js/123 с заголовком Accept-Encoding: sbr,br,gzip, где 123 — скажем, порядковый номер пайплайна

2. Сервер отвечает ассетом с заголовками use-as-dictionary: p="/app/main.js" и Vary: Accept-Encoding, sec-available-dictionary

3. Бразуер кеширует ассет /app/main.js и его хеш-сумму SHA-256

4. Во время следующего билда генерируется delta-compressed словарь для main.js — т.е. берётся разница между ассетами, для этой разницы генерируется Brotli словарь и соханяется под main.js.<hash>.sbr

5. Пользователь снова заходит на сайт, но браузер делает запрос за static.example.com/app/main.js/124, т.к. мы раздаём новый билд

6. Браузер матчит запрос на основе заголовка use-as-dictionary и делает новый запрос с Accept-Encoding: sbr,br,gzip и sec-available-dictionary: <SHA-256 HASH>, который сохранился на 3 пункте

7. Сервер отвечает словарем, полученым на 4 шаге, в котором хранится разница между билдами, и заголовками Content-Encoding: sbr и Vary: Accept-Encoding, sec-available-dictionary



Как итог, в повторный визит скачивается только та самая разница в виде main.js.<hash>.sbr с 4 шага и распаковывается, а если пользователь зашёл впервые, то ассет отдаётся как обычно.



Сложно сказать, когда оно появится в браузера, но ребята из хрома высказали желание реализовать эксперимент (более того, в ишью есть инфа о том, что похожая фича была доступна 7 лет назад).



Ишью с идеей: https://github.com/WICG/proposals/issues/90

Детальное разъяснение: https://github.com/WICG/compression-dictionary-transport



P.S. Честно, сложновато рассказывать о том, в чём сам так себе разбираешься, так что рекомендую, как обычно, сходить по ссылкам. Там умные люди всё за меня расписали. Так же я без понятия как проводят инициативы в WICG, так что какие-то прогнозы по срокам писать не берусь.