В этом исследовании мы показываем, что даже если новый HTTP/2 протокол значительно улучшает скорость загрузки страницы, время для полного отказа от фронт-энд оптимизаций ещё не наступило. Сегодня мы сосредоточимся на спрайт-сетах.
HTTP/2 стал доступен в 2015, как альтернатива к замене многоуважаемого HTTP/1.1, используемого с 1997. Многие авторы предсказывают устаревание или, даже, контрпродуктивность фронт-энд оптимизаций. В список классических оптимизаций входят спрайты: группировка множества маленьких изображений (спрайтов) в одно большое (спрайт-сет).
Несмотря на быстрое внедрение поддержки и в браузерах и в серверах (вики, w3techs), мы не смогли найти опубликованные сравнительные замеры для подтверждения утверждения (прим. того, что спрайты больше не нужны). Как веб-архитекторы, тогда, мы естественно, интересовались, следует ли нам отказаться от подхода спрайтов или нет. Как гласит известная цитата Уильяма Эдвардса Деминга: “In God we trust, all others bring data”. Поэтому мы сделали свой собственный бенчмарк.
Первая часть этой статьи описывает основные отличия между HTTP/1.x и 2 и почему они могут способствовать устареванию спрайтов. Во второй части мы покажем сравнительные результаты бенчмарка.
Спрайт-сеты
Спрайт-сеты это фронт-энд оптимизация. Вместо загрузки нескольких изображений с сервера по одному (к примеру, набор иконок, которые используются по всей странице), один спрайт-сет загружается единожды и в дальнейшем, каждый спрайт может быть вырезан. Спрайт-сет используемый в нашем бенчмарке с сайта www.facebook.com показан на Рис. 1.
Рис. 1: спрайт-сет бенчмарка.
Этот спрайт-сет составлен из 72 спрайтов, которые могут быть точно вырезаны в маленькие индивидуальные изображения каждого спрайта.
Первое что бросается в глаза, это то, что спрайт-сет как единое глобальное изображение весит всего 71 kB, в то время как спрайты, как отдельные изображения, в сумме 106 kB, больше, почти на 40 %. Объединённый размер меньше чем сумма, благодаря лучшему сжатию изображения и уменьшению избыточных заголовков изображений. Более того, одного запроса на сервер достаточно для загрузки всех иконок сайта со спрайт-сетом, вместо множества запросов по одному на каждое изображение.
Для того чтоб отрисовать картинки в браузере, спрайт-сет нарезается на маленькие иконки в CSS коде. На Рис. 2 вы можете видеть HTML используемый с/без использования спрайтов, и соответствующие CSS стили. Результирующая нагрузка также отображена на графике.
CSS с отдельными изображениями | HTML (общий) | CSS со спрайт-сетом |
---|---|---|
|
|
|
Рис. 2: с/без использования спрайт-сетов.
Два изображения захвата HTTP запросов. Без спрайт-сета можно заметить несколько параллельных небольших запросов с суммарно большим временем завершения.
Очевидно, что CSS код значительно проще без спрайт-сета, однако время загрузки значительно короче с использованием спрайтов. При использовании спрайт-сетов возникает несколько технических накладок, они будут оговорены ниже.
Основные же ограничения подхода спрайт-сетов такие:
- более сложная разработка поскольку необходимо создавать или адаптировать спрайт-сет и поддерживать CSS код для разделения его на отдельные иконки. Несмотря на это, процесс может быть автоматизирован в разработке с инструментами типа Glue;
- обновление браузерного кеша при каждой модификации спрайт-сета, даже если это просто добавление, удаление или модификация одного спрайта.
HTTP/1.x и спрайты
В HTTP/1.x не более одного запроса (прим. одновременно) возможно в пределах одного TCP соединения между клиентом и сервером. Следующие запросы должны ждать в очереди для того, чтобы переиспользовать TCP соединение. В целях уменьшения времени загрузки и во избежание зависания страницы из-за одного длительного запроса, современные браузеры открывают несколько параллельных TCP соединений с сервером (как правило, от 2 до 8 соединений, в зависимости от браузера). Тем не менее, такое распараллеливание ограничено и использование большого количества запросов всё ещё значит что время загрузки будет больше, а сеть перегружена, даже не учитывая бэк-энд сторону.
Загрузка всех независимых изображений за раз приводит к множеству запросов в HTTP/1.x и сильно влияет на итоговое время загрузки, отсюда и на UX, в то время как использование спрайт-сета в результате приведёт к одному запросу что является огромной оптимизацией на многих веб-сайтах.
HTTP/2 и спрайты
С HTTP/2 все запросы между браузером и сервером мультиплексированы (прим. уплотнены) в одно TCP соединение.
Компенсируя стоимость открытия и закрытия множества соединений это приводит к лучшему использованию TCP соединения и ограничивает влияние на задержки между клиентом и сервером.
Это позволяет загружать десятки изображений в параллели в одном TCP соединении. Как следствие, использование спрайт-сетов для уменьшения количества запросов может стать бесполезным. Все эти предложения (прим. фразы) пока являются гипотезами: эта статья покажет как реальность отличается от теории.
Методология бенчмарка
Весь код для повторения этого бенчмарка доступен на Github.
Для воспроизведения различных ситуаций, были созданы шесть HTML страниц. Первая из них использует спрайт-сет, остальные же, включают в себя различные количества отдельных изображений.
Имя настройки | Изображения | Кол-во |
---|---|---|
Single | спрайт-сет | 100% (72) |
AllSplitted | отдельная | 100% |
80pSplitted | отдельная | 80% |
50pSplitted | отдельная | 50% |
30pSplitted | отдельная | 30% |
10pSplitted | отдельная | 10% |
Последние четыре страницы, только с частью спрайтов, показывают наиболее распространённую ситуацию, когда все спрайты не используются одновременно: необходима только часть изображений, в зависимости от контекста (язык, геолокация, состояние приложения и т.п.). Использование отдельных изображений вместо спрайт-сетов позволяет загружать только те из них, которые нужны из всей коллекции. Однако результаты продемонстрируют как группировка остаётся эффективной.
В нашем бенчмарке был разработан JavaScript код для вычисления промежутка времени между окончанием загрузки HTML страницы (исполнения скриптов в заголовке страницы) и загрузкой последнего изображения (последнего события onload
). Этот промежуток времени рассчитан и записан для каждого случая. Страницы и изображения были загружены на два сервера NGINX 1.9.5 расположенные в одном датацентре на двух идентичных виртуальных машинах.
Один сервер поддерживает HTTP/2, в то время как другой поддерживает только HTTP/1.1. Страницы запрашиваются через HTTPS, даже с HTTP/1.1, для того, чтобы сравнение проходило максимально честно по отношению к HTTP/2 который поддерживает только защищённую передачу.
На стороне клиента был разработан Python скрипт для запроса страниц через два браузера, Firefox 41.0 и Chrome 45.0 (прим. актуальные версии на момент написания статьи), запускаемые через Selenium WebDriver. Selenium позволяет иметь новый контекст в браузере для каждого запроса для избежания эффекта кеширования. Конечно, если изображения кешировались бы браузером, мы не смогли бы протестировать протокол поскольку там не было бы реальной передачи (только пустое тело с кодом 304). Selenium также позволяет просто проверять DOM для получения временного промежутка рассчитанного JavaScript'ом и выведенного на странице.
Рис. 3: архитектура кода тестирования.
В целях получения надёжных результатов, протокол запускается сто раз для каждого случая, как показано в псевдокоде ниже.
for i = 1 to 100
for page in ('Single', 'AllSplitted', '80pSplitted',
'50pSplitted', '30pSplitted', '10pSplitted')
for protocol in ('HTTP/1.1', 'HTTP/2')
for browser in ('Firefox', 'Chrome')
#load page and measure load time
Для каждого случая записывается значение медианы. Если посмотреть на распределение времени для одного случая (см. Рис. 4), мы наблюдаем резко выделяющиеся значения, обусловленные изначально стохастическим (прим. случайным) процессом сети. Влияние этих точек на среднее значение будет велико. С другой стороны медиана является надёжным индикатором поскольку распределение практически однородное.
Рис. 4: исходные данные времени загрузки, при повторении вычисления сто раз.
Для расширения области актуальных ситуаций, протокол был повторён на трёх конфигурациях клиента:
конфигурация | описание | средняя задержка | пропусканая способность загрузки |
---|---|---|---|
#1 | ВМ в хорошем датацентре | 10ms | 80Mb/s |
#2 | ноутбук с хорошим интернет соединением | 40ms | 20Mb/s |
#3 | ноутбук с плохим интернет соединением | 35ms | 1.3Mb/s |
Результаты бенчмарка
Три конфигурации дали очень когерентные (прим. логически последованные) результаты, показанные на Рис. 5.
Рис. 5: суммарные медианы загрузки для разных типов страниц, браузеров, http протоколов и конфигураций сети.
По графикам видно, что:
- время загрузки спрайт-сета равно или меньше, чем 10% отдельных изображений, даже при соединении с низкой задержкой. На других конфигурациях спрайт-сет значительно быстрее загружается чем индивидуальные спрайты, вне зависимости от используемого HTTP протокола;
- HTTP/2 приносит очевидное уменьшение времени загрузки в сравнении с HTTP/1.1, но улучшение HTTP протокола не является достаточным для уменьшения полезности фронт-энд оптимизаций;
- при текущих замерах браузер незначительно влияет на разницу (разница времени загрузки на конфигурации #1 возможно вызвана ограничением CPU и памяти на виртуальной машине).
Для дальнейшего анализа этих результатов можно также отобразить на графике медианное время загрузки в соотношении к кол-ву запросов или сумме размеров изображений. Рис. 6 показывает результаты для вышеописанной конфигурации #3.
Рис. 6: те же эксперименты, как и на Рис. 5, с конфигурацией #3, но сравнивая зависимость времени к кол-ву изображений и сумме размеров изображений.
На основании этих двух графиков можно судить о том, что подход спрайт-сетов сильно отличается от отдельных спрайтов из-за использования одного запроса, в то время как суммарный размер выступает вторым по влиянию на скорость.
Заключение
Этот бенчмарк явно отстаивает что оптимизация спрайт-сетами всё ещё актуальна, даже после апгрейда на протокол HTTP/2. Даже не смотря на то, что новый протокол предлагает значительное улучшение времени загрузки (до 50%) в сравнении с HTTP/1.1, этого может быть недостаточно. Если HTTP/2 оптимизирует использование сети, это не станет основанием для полного отказа от фронт-энд оптимизаций, среди которых спрайт-сеты, CSS/JS минификации и бандлы.
Прим. переводчика: в статье есть некоторые устаревшие данные обусловленные датой выхода статьи (декабрь 2015 года), однако основной посыл остаётся актуальным.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Комментарии (41)
Sulin
01.09.2016 09:55ну да на количестве запросов несомненная экономия. НО при заходе пользователя вы ему отдаёте весь спрайт с кучей иконок, но на той странице что открыл пользователь использоваться может меньше половины тех что в спрайте, в результате вы отдаёте лишние килобайты пользователю каждому вместо того что бы отдать непосредственно то что нужно, а что будет быстрее отдать весь спрайт в 71 kb или отдать 10 запросами нужные иконrи на 30 kb тут нужно еще замерять. (не стоит забыть про многопоточность загрузки браузером + про вынос статики на поддомен.)
Sioln
01.09.2016 10:21И стоит ещё провести сравнение — не окажется ли такая оптимизация "микро", по сравнению с выносом статики на CDN.
esc
01.09.2016 10:30Если вы вынесете статику с сыром виде (без объединения мелких файлов в один большой), то это будет практически так же плохо, как и отдача их со своего сервера. А если соберете в кучу, то cdn даст эффект только если на сайт ходят пользователи с разных уголков планеты (но тут надо будет решить, как быть с html).
Да и в случае нормальной оптимизации и канала на сервере, этот эффект будет не очень весомым т.к. ускорит работу пользователей провайдеров у который есть сильный приоритет локального трафика (допустим, канал у провайдера гигабит на мир и по гигабиту в каждую локальную точку обмена). Если у пользователя хороший интернет, то малое количество больших файлов он скачает не хуже, чем пользователь где-то рядом.keydon2
02.09.2016 02:22Почему статика в сыром виде будет так же плоха?
Все картинки могут быть принудительно заранее закэшированы на всех серверах CDN. CDN также может раздавать по HTTP2esc
02.09.2016 09:39Потому, что статика с CDN будет раздаваться так же медленно, как и с сервера сайта. Разница будет только если пользователь на другом конце света. Но даже в этом случае, множество запросов и ответов увеличат время загрузи и возможно это будет медленнее, чем отдать весь спрайт с далекого но быстрого сервера.
esc
01.09.2016 10:2610 запросов будут скорее медленнее даже на мобильном интернете. Часто скорость отдачи данных сильно меньше скорости приема и для мобильного интернета это выльется в то, что ожидание каждой картинки будет довольно длительным.
Плюс спрайта в том, что при переходе на другую страницу, спрайт (а так же стили и js) будут уже взяты их кэша и запросов за ними вообще не будет. А если страница такого сценария не предполагает (допустим, строго одностраничный сайт), то лучше собрать просто правильный спрайт без лишних данных, чем отдавать 10 отдельных картинок.Sulin
01.09.2016 11:23на медленном интернете как раз думаю спрайт еще больше проигрывает, особенно в отзывчивости страницы, я имею ввиду что на медленном интернете вы будете например секунду ждать загрузки самого спрайта и пока он весь не загрузится вы не увидите ни одной иконки на сайте, а если их грузить отдельно то как только иконка загрузится она уже будет отображена даже если все остальные еще не загрузились, в результате отображение хоть чего-то на странице вы увидите раньше чем если бы это был один тяжёлый спрайт.
miksoft
01.09.2016 11:31а если их грузить отдельно то как только иконка загрузится она уже будет отображена даже если все остальные еще не загрузились, в результате отображение хоть чего-то на странице вы увидите раньше чем если бы это был один тяжёлый спрайт.
К сожалению, на многих сайтах это «отображение хоть чего-то» будет еще несколько секунд дергаться, перерисовываясь после загрузки очередной иконки.Sulin
01.09.2016 12:25и все же дёрганье при перерисовке думаю лучше чем просто пустой экран непонятный пользователю, то ли сайт грузится то ли все зависло и нужно закрывать это всё побыстрее.
esc
01.09.2016 13:57Пустого экрана от спрайтов не будет, это ж не css. Да и разница между тем, что отображается на конкретной странице и общим содержимым спрайта редко бывает большой.
Sulin
01.09.2016 14:01«пустой экран» — это я образно. в любом случае мелки иконки начнут отображаться раньше чем спрайт, может они и будут в общем дольше грузится, но пользователю они показываться будут раньше. и тут уже с точки зрения скорости загрузки спрайт может лучше, а с точки зрения удобства для пользователя то отдельные иконки были бы лучше.
extempl
01.09.2016 14:07Ну удобство для пользователя тоже спорный момент. Например, именно для удобства пользователя стали собирать состояния кнопки/иконки в один сет, для того, чтоб при наведении курсора не ждать, пока подгрузится картинка изменившегося состояния (она загружается вместе с исходным состоянием).
Для того, чтоб ничего не прыгало, следует указывать размеры блока, в котором находится картинка. Что, впрочем, не всегда возможно. Тем не менее, что удобнее — появляющиеся в рандомном порядке 10 (например) иконок или появление их одновременно всего через секунду, а то и пол — вопрос.
esc
01.09.2016 14:08Если спрайт разумного размера, то загрузится он не сильно дольше, чем отдельные иконки. Потому, что для каждой иконки отдельный исходящий запрос (а это боль на мобильном интернете), отдельные заголовки как при получении, так и при запросе и потом браузер для каждой картинки будет создавать объект и т.д. В итоге, страница будет хреново работать, пока эти картинки прогружаются, если у пользователя слабое устройство.
Pakos
02.09.2016 09:33В отзывчивости зачастую выигрывает — при большом пинге на могильном интернете каждая картинка подгружается с заметной паузой — заметил, когда с такого пришлось зайти на сайт с кучей мелких картинок (инет 4G — видео можно смотреть и ютуб по дефолту FHD подсовывает, но вот соединения — ужасны).
Sulin
01.09.2016 11:33Вообще думаю в первую очередь стоит не считать кол-во соединений, а расчитать количество пакетов для отправки этих картинок внутри соединения, для каждого пакета будет свой доп. RTT. соответственно картинка в 14 килобайт уйдёт 1 пакетом, а картинка в 15 килобайт двумя пакетами, и хотя разница всего 1 килобайт буден 1 дополнительный RTT. для 1 соединения нужно минимум 3 RTT а дальше зависит от размера файла сколько их еще будет сверху. поэтому думаю в первую очередь нужно такие картинки весом в 15 килобайт ужать чутка до 14 килобайт и уже будет экономия в скорости загрузки на 1 RTT. а уже потом думать как уменьшить количество соединений.
miksoft
01.09.2016 11:37соответственно картинка в 14 килобайт уйдёт 1 пакетом, а картинка в 15 килобайт двумя пакетами
Скорее будет 10 и 11 пакетов соответственно.
Но да, согласен, round trip-ы надо экономить.
orgkhnargh
01.09.2016 11:59+1Может с server push разница не будет так заметна, а в реальных сценариях использования будет выигрыш за счет пропуска неиспользуемых спрайтов (зачем мне 4 набора спрайтов глобуса, если 3 из них я никогда не увижу?) и более оптимальной работы кэша (при редактировании одного спрайта необходимо перезагрузить лишь измененный спрайт вместо всего суперспрайта)?
esc
01.09.2016 13:59Потому, что объем картинки такого глобуса, который вы никогда не увидите, сравним с объемом заголовков в запросе. Только запрос еще и надо обрабатывать, тогда как дополнительный глобус никаких действий не требует и оверхед от него минимальный, если вообще есть с учетом заголовков.
homm
02.09.2016 19:58Но ведь в статье именно это и тестируется — худший случай, когда используется только 10% изображений из спарйта.
G-M-A-X
01.09.2016 21:30-2Использование http/2 ведет к использованию шифрования.
Если отдавать много жирной статики, то будет дополнительная нагрузка на проц для ее шифрования.
А также задержку дает начальная установка соединения.
Для себя пока остаюсь на http, никаких секретных данных не передается, ну кроме паролей.
А также сертификат стоит денег.
А также не все сервера его поддерживают (шаред-хостинги).sumanai
02.09.2016 01:12+5А также сертификат стоит денег.
А также не все сервера его поддерживают (шаред-хостинги).
Как там, в 2013?
Для бесплатных сертификатов уже даже выбор есть, я знаю три центра выдачи бесплатных сертификатов.
Благодаря SNI нормальные шареды поддерживают TLS без выделения отдельного IP, а благодаря автоматической выдаче Let's Encrypt для его настройки нужно только галочку поставить, всё остальное сделают скрипты хостинга, включая получение и обновление сертификата.G-M-A-X
02.09.2016 14:20Для бесплатных сертификатов уже даже выбор есть, я знаю три центра выдачи бесплатных сертификатов.
С тем, что столкнулся, это какая-то муть. Для какого-то сертификата нужно на сервере установить демон, который будет ходить и обновлять сертификат, так как он выдается на 3 мес. Дополнительная дыра в безопасности. Да и на шареде не будет работать. (перечитал ваш коммент до конца, да это, вроде и был Let's Encrypt)
Но да, есть бесплатные cloudflare при использовании его cdn, работает автоматом и ничего настраивать не нужно.
Благодаря SNI
Я имел в виду не поддерживают http/2, но и касательно SNI — он тоже не везде.
Хотя, кому нужен https, они на него перейдут, но вряд ли из-за http/2. http/2 — это бонус.sumanai
02.09.2016 16:13Для какого-то сертификата нужно на сервере установить демон, который будет ходить и обновлять сертификат, так как он выдается на 3 мес.
Не хотите на три месяца, берите StarSSL на год. Не хотите на год, есть сертификаты от китайских друзей на 2 года, до 5 доменов в одном сертификате.
Ах да, спасибо за напоминание про cloudflare, способов получить бесплатный сертификат уже четыре.
Да и на шареде не будет работать
Будет, если предоставляется самим хостером. И дыры в этом софте- его проблема.
homm
02.09.2016 16:47В HTTP/1.x не более одного запроса (прим. одновременно) возможно в пределах одного TCP соединения между клиентом и сервером.
Это не так. Запросы в HTTP/1.1 можно пайплайнить. К сожалению, браузеры этим не пользуются из-за возможности наткнуться на том конце на сервер, который плохо работает с пайплайнами (из популярных и современных таких нет, но все же).
Iskin
02.09.2016 20:26+1Исследование в статье неверное, так как строится не неправильном понимании HTTP/2. Просто смена протокола даёт не самое большое ускорение и не позволяет заменить спрайты. Но протокол даёт новые инструменты, с помощью которых как раз можно и добиться существенного ускорения.
Для замены спрайтов есть специальный инструмент pre-push. Это когда сервер может ответить сразу несколькими файлами на один запрос. Например, пользователь запрашивает index.html, а сервер сразу отвечает index.html, app.css, logo.png, img1.png, img2.svg.
Очевидно, что pre-push как раз позволяет сделать такой аналог спрайта (все файлы уходят на один запрос). pre-push даже гораздо лучше спрайтов, так как в одном ответе может быть и HTML, и PNG, и SVG.
Кроме того, pre-push может быть гораздо умнее спрайтов и отвечать только новыми картинками, если только часть из них обновилась.
Соответственно, нужно тестировать не просто HTTP/2, а новый веб-сервер, который поддерживает pre-push. К сожалению, такого сервера (или сборщика) ещё нет. Поэтому все разговоры про то, что HTTP/2 уже здесь — преждевременные.sumanai
02.09.2016 20:52Кроме того, pre-push может быть гораздо умнее спрайтов и отвечать только новыми картинками, если только часть из них обновилась.
И это превращает легковесный вебсервер в нечто тяжёлое и неповоротливое. С наличием своего состояния, с которым борются даже на бекенде.Iskin
02.09.2016 20:54Как конкретно делать pre-push — второй вопрос. Можно заранее составить картинку зависимостей. И использовать какой-то аналог E-Tag на клиенте (старый E-Tag не подойдёт)
homm
02.09.2016 21:28Например, пользователь запрашивает index.html, а сервер сразу отвечает index.html, app.css, logo.png, img1.png, img2.svg.
А ты давно делал приложение, в котором index.html, app.css и logo.png были на одном сервре или одном домене?
И использовать какой-то аналог E-Tag на клиенте (старый E-Tag не подойдёт)
Поправь, если неправ, но вроде браузеры не посылают никакой новый e-tag, который нам позволил бы узнать, что у браузера уже есть в кеше. А значит протокол не даёт новые инструменты, с помощью которых можно добиться существенного ускорения.
Iskin
02.09.2016 21:29Разносить на разные сервера нужно было в HTTP/1 из-за ограничения кол-ва запросов. В HTTP/2 весь смысл этого пропадает.
homm
02.09.2016 21:35Не из-за ограничения кол-ва запросов, а потому что сервер со статикой легко и просто расположить у пользователя под боком (CDN), а сервер с приложением нет.
Iskin
02.09.2016 21:37Да, хороший вопрос, как делать CDN на базе HTTP/2. Можно сделать в виде прокси-сервера. Клиент подключается в CDN и запрашивает index.html. CDN проксирует запрос на index.html в главные сервера, а сам в это время начинает отдавать статику (по заранее подготовленной сборщиком таблице зависимостей)
Iskin
02.09.2016 21:30«Замену E-Tag» можно сделать через обычный cookie.
homm
02.09.2016 21:38Но получается, нужно будет в куку пихать ключ: значение, где ключи — путь к статике, а значение — ревизия. Это очень много для куки — в примере из статьи в спрайте 72 картинки. Если сделать одну общую ревизию на всю статику, мы возвращаемся к тому, что при изменении одного файла будет скачиваться вся статика (на этот раз она будет пушится).
Iskin
02.09.2016 21:46+1Можно проще — положить куку last_request со временем последнего запроса. Если статика изменилась с последнего запроса — шлём новую версию.
sumanai
03.09.2016 13:09А если клиент закешировал весьма старый контент, а продолжах ходить с ним? Кука last_request будет обновляться, а кеш уже устареет.
Firefoxic
03.09.2016 11:40+1Всё равно его не брошу, потому что он хороший?
Кто в здравом уме будет внедрять в свои проекты такие новейшие технологии, как HTTP/2, и при этом тащить этот антиквариат в виде png-спрайта из одноцветных простейших иконок, да ещё и большая часть которых — шестикратное повторение одного и того же но с другим цветом? Может всё-таки сначала надо свой фронтенд подтянуть и заменить таки png на svg (для иконок как минимум), а потом уже тюнинговать сервак и думать, спрайт или не спрайт?
petertretyakov
Из этой статьи я узнал, что Facebook использует разные иконки глобусов для пользователей из разных стран.