Почему 14 KB?
Вот в пример реальные запросы.
Вот сайт который влезает в 14кб:

А вот который не влезает:

Download - это и есть наш контент
1 ms против 63 ms.
Разница времени загрузки - 63 раза
Разница полезного веса - 7 раз
TCP Slow Start
В том то и ёбень, что TCP не отдаст контент одним пакетом. Даже когда сервер готов ответить, TCP говорит: “погоди братуха, у нас congestion control”: р Он начинает с initcwnd - 10 сегментов (RFC 6928) - это 1460байт.
- Сервер послал 14 KB - ждёт ACK,
- Пришёл ACK - окно удвоилось до 20 сегментов (~29кб),
- Послал теперь 29KB - снова ждёт…
И так пока не передаст всё.
Каждый луп - это RTT.
Чем больше ответ - тем больше rounds.
Если ответ влазит в 14.6 KB - он улетает одним пакетом.
Без ожидания && без удвоения && без лишних RTT.
:: One round trip.
На больших файлах (картинки и прочий тяжелый контент) эта особенность уже не доставляет проблем, т.к. tcp успевает разогнаться.
Но в бол-ве случаев на сайтах файлы меньше 100кб - и это уже реальная проблема.
И это при условии что у тебя всего один запрос. А если отдельно шрифты, скрипты, картинки - каждый из них проходит полный круг заново. Со своим setup, своим slow start, своими RTT. Один сайт превращается в 5-10-30 последовательных запросов, и каждый жрёт время на общение протоколов, а не передачу полезных данных.
В качестве плохого примера - сайт New-York Times - 891 http запрос на 9мб контента, 6 секунд blocking time, хотя сайт - буквально стандартный газетный layout, где ничего тяжелого быть не может.
Клубы
Есть 14KB Club - сайты до 14 KB сырыми. Там считают uncompressed size, т.е. по сути туда не пустят сайт, что весит условные 20-30кб, но благодаря сжатию gzip может уместиться в 1rtt - спорный момент правил.
512KB Club - не влезать сюда - ебейшее неуважение к пользователям и к интернету в целом. Удаляйте свой сайт нахуй.
данный бугурт не относится к полезной информации на сайте, по типу фото-видео
Мои потуги
Есть у меня сайтец sccl.cc.
Запилен на Zine - SSG на Zig. Три страницы: contacts, projects, peripherals.
Исходно сервер отдавал:
- HTML (~15kb)
- Space Mono 400 woff2 (~40kb)
- Аватарка png (~2mb)
- Фавикон png (~1mb)
на скрине уже немного заоптемайзенный, было хуже :skull:
(до переезда на zine был ваще 150+кб, см Migration-from-Astro-to-Zine.md)
Четыре запроса на страницу, на контент, который суммарно нихрена не весит.
Всё это с учётом что полный setup (DNS + TCP + TLS) происходит один раз (keep-alive, HTTP/2). Но даже так - на каждую вкладку, на каждый переход с другой страницы - новый setup. А шрифт и аватарка висят отдельными запросами.
Оптимизация
План: всё в один HTML. Base64 инлайн всего, ноль внешних запросов. И чтоб влезало в initcwnd.
Шрифт
Самый жирный момент - у меня было 2 шрифта и жирные версии к ним.
Было решено выкинуть всё, кроме одного.
а из файла шрифта выкинуть всё кроме ASCII символов, которые реально юзаются на сайте.
Отключить хинтинг, отключить layout features.
Итог: 4.2кб. Потом base64 в @font-face → 5.7кб текста в HTML.
Это единственная уступка эстетике. Лучше конечно вообще без кастом шрифтов.
Аватарка
Инишиал был ультра жирныч.
Но шаклозатором кортинка сначал была ужата до трёх цвета.
И в PNG весела 1.9kb.
При переконверте в WebP: стало 702 b. Base64 → 940 B.
Фавиконка
199b, осталась в png.
268b в base64.
JS
По хорошему тут можно было прям люто резать, но у меня удалось сохранить весь функционал на сайте и пихнуть весь js inline. У меня там и анимированные кнопки, анимированный фон и пасхалска с анимацией - крч всё лишнее говно, без которого можно было бы хоть в 5кб сайт ужимать. (что не дало бы скорости)
Итог
До: 4 запроса, ~50kb суммарно
После: 1 запрос, 12kb gzip / 27kb raw
Влезает в initcwnd. Один TCP-пакет. Один round trip на данные.

Дилемма
Инлайн всего - это компромисс.
При переходе на другую страницу браузер качает тот же шрифт по новой - шрифт внутри HTML, он не кешируется отдельно. С отдельным файлом шрифт закешировался бы после первого раза, и вторую страницу качал бы без него.
Так же стоит учитывать что инлайн обычно весит чуть больше чем внешняя зависимость, и если мы и так не лезем в initcwnd - то и инлайн нам ненужен.
Пример
1. Всё в одном HTML (base64 шрифты)
- 2 страницы по 14кб каждая
- каждая грузится за 1 round trip
- но каждый раз жрёшь полные 14кб, даже если шрифт повторяется
2. HTML + отдельный шрифт
- 2 страницы по 8кб + шрифт 4кб отдельно
- первый заход: 2 запроса (HTML + шрифт)
- переход между страницами: только 8кб (шрифт закеширован)
В реальном интернете разницы между скоростью загрузки 14кб и 8кб - не почувствовать.
А делеи между пакетами - да.