В последние годы всё больше платформ для оптимизации фронтенд-проектов предлагают возможности по самостоятельному хостингу или проксированию сторонних ресурсов. Akamai позволяет задавать специфические параметры для самостоятельно создаваемых URL. У Cloudflare есть технология Edge Workers. Fasterzine может переписывать URL на страницах так, чтобы они указывали бы на сторонние ресурсы, находящиеся на основном домене сайта.
Если известно, что сторонние сервисы, используемые в вашем проекте, изменяются не слишком часто, и то, что процесс их доставки клиентам может быть улучшен, то вы, наверняка, задумываетесь о проксировании подобных сервисов. При таком подходе вы вполне можете «приблизить» эти ресурсы к пользователям и обрести более полный контроль над их кэшированием на клиентской стороне. Это, кроме того, позволяет защитить пользователей от неприятностей, вызванных «падением» стороннего сервиса или деградацией его производительности.
Хороший: повышение производительности
Самостоятельный хостинг чужих ресурсов улучшает производительность вполне очевидным образом. Браузеру не нужно лишний раз обращаться к DNS, ему не надо устанавливать TCP-соединение и выполнять TLS-рукопожатие на стороннем домене. То, как самостоятельный хостинг чужих ресурсов влияет на производительность, можно увидеть, сравнив два следующих рисунка.
Сторонние ресурсы загружаются из внешних источников (взято отсюда)
Сторонние ресурсы хранятся там же, где и остальные материалы сайта (взято отсюда)
Ситуацию улучшает ещё и то, что браузер будет использовать возможности по мультиплексированию и приоритизации данных HTTP/2-соединения, которое уже установлено с основным доменом.
Если не размещать у себя сторонние ресурсы, то, так как они будут загружаться с домена, отличного от основного, их нельзя будет приоритизировать. Это приведёт к тому, что они будут конкурировать друг с другом за полосу пропускания клиента. Это может привести к тому, что время загрузки материалов, критически важных для формирования страницы, окажется гораздо большим, чем время, достижимое при идеальном стечении обстоятельств. Вот выступление об HTTP/2-приоритизации, в котором всё это очень хорошо разъясняется.
Можно предположить, что использование в ссылках на внешние ресурсы атрибутов preconnect
поможет в решении проблемы. Однако если таких ссылок на различные домены будет слишком много, это может, на самом деле, перегрузить линию связи в самый ответственный момент.
Если хостить сторонние ресурсы самостоятельно — можно контролировать то, как именно эти ресурсы отдаются клиенту. А именно, речь идёт о следующем:
- Можно обеспечить применение алгоритма сжатия данных, наилучшим образом подходящего для каждого браузера (Brotli/gzip).
- Можно увеличить время кэширования ресурсов, которые обычно, даже у наиболее известных провайдеров, не особенно велико (например, соответствующее значение для тега GA установлено в 30 минут).
Можно даже расширить показатель TTL для ресурса, например, до года, включив соответствующие материалы в свою стратегию управления кэшированием (URL-хэши, версионирование и так далее). Об этом мы поговорим ниже.
▍Защита от перебоев в работе сторонних сервисов или от их отключения
Ещё один интересный аспект самостоятельного хостинга сторонних ресурсов заключается в том, что это позволяет смягчить риски, связанные с перебоями в работе сторонних сервисов. Предположим, что используемое вами стороннее решение для проведения A/B-тестирования реализовано в виде блокирующего скрипта, загружаемого в заголовочном разделе страницы. Этот скрипт загружается медленно. Если соответствующий скрипт загрузить не удастся — будет пустой и страница. Если на его загрузку потребуется очень много времени — страница появится с большой задержкой. Или, предположим, в проекте используется библиотека, загружаемая со стороннего CDN-ресурса. Представим, что этот ресурс испытал сбой или был заблокирован в некоей стране. Подобная ситуация приведёт к нарушению логики работы сайта.
Для того чтобы узнать о том, как ваш сайт работает в условиях недоступности некоего внешнего сервиса, можете воспользоваться разделом SPOF на webpagetest.org.
Раздел SPOF на webpagetest.org
▍Как насчёт проблем с кэшированием материалов в браузерах? (подсказка: это миф)
Можно подумать, что использование общедоступных CDN автоматически приведёт к лучшей производительности ресурсов, так как эти службы обладают достаточно качественными сетями и распределены по всему миру. Но всё, на самом деле, немного сложнее.
Предположим, у нас имеется несколько разных сайтов: website1.com, website2.com, website3.com. На всех этих сайтах используется библиотека jQuery. Мы её к ним подключаем, пользуясь CDN, например — googleapis.com. Можно ожидать, что браузер один раз загрузит и кэширует библиотеку, а потом будет использовать её при работе со всеми тремя сайтами. Это могло бы уменьшить нагрузку на сеть. Возможно, это позволит где-то сэкономить и поможет улучшить производительность ресурсов. С практической же точки зрения всё выглядит иначе. Например, в Safari реализована возможность, называемая Intelligent Tracking Prevention: в кэше используются двойные ключи, основанные на источнике документа и на источнике стороннего ресурса. Вот хорошая статья на эту тему.
Старые исследования Yahoo и Facebook, а так же более свежее исследование Пола Кальвано, показывают, что ресурсы не хранятся в браузерных кэшах так долго, как мы могли бы ожидать: «Имеется серьёзный разрыв между временем кэширования собственных и сторонних ресурсов проекта. Речь идёт о CSS и о веб-шрифтах. А именно, срок кэширования 95% собственных шрифтов превышает неделю, в то время как срок кэширования 50% сторонних шрифтов составляет меньше недели! Это даёт веб-разработчикам веские основания для самостоятельного хостинга файлов шрифтов!».
В результате, если вы будете хостить у себя чужие материалы, то не заметите проблем с производительностью, вызванных браузерным кэшированием.
Теперь, когда мы рассмотрели сильные стороны самостоятельного хостинга сторонних ресурсов, давайте поговорим о том, как отличить хорошую реализацию этого подхода от плохой.
Плохой: дьявол кроется в деталях
Перемещение сторонних ресурсов на собственный домен нельзя выполнить автоматически, не позаботившись о правильном кэшировании таких ресурсов.
Одна из основных проблем здесь — время кэширования. Например, сведения о версиях включаются в имена сторонних скриптов примерно так: jquery-3.4.1.js
. Такой файл в будущем не изменится, в результате это не вызовет каких-либо проблем с его кэшированием.
Но если некая схема версионирования при работе с файлами не применяется, кэшированные скрипты, содержимое которых меняется при неизменном имени файла, могут устаревать. Это способно стать серьёзной проблемой, так как это, например, не позволяет в автоматическом режиме вносить в скрипты исправления безопасности, которые как можно скорее должны получить клиенты. Разработчику придётся приложить усилия к тому, чтобы обновить подобные скрипты в кэше. Кроме того, это может вызвать сбои в работе приложения, вызванные тем, что код, используемый на клиенте из кэша, отличается от свежей версии кода, на которую рассчитана серверная часть проекта.
Правда, если говорить о материалах, которые обновляются часто (менеджеры тегов, решения для A/B-тестирования), то их кэширование средствам CDN — задача хотя и решаемая, но уже гораздо более сложная. Сервисы вроде Commanders Act, решения для управления тегами, при публикации новых версий используют веб-хуки. Это даёт возможность организовать сброс кэша на CDN, или, что ещё лучше, возможность вызова обновления хэша или версии URL.
▍Адаптивная выдача материалов клиентам
Кроме того, когда мы говорим о кэшировании, нужно учитывать и тот факт, что настройки кэширования, используемые на CDN, могут не подходить для неких сторонних ресурсов. Например, такие ресурсы могут использовать технологию сниффинга пользовательского агента (user agent sniffing, adaptive serving) для того, чтобы выдавать конкретным браузерам версии материалов, оптимизированные специально для этих браузеров. Эти технологии, для того, чтобы выяснить возможности браузера, полагаются на регулярные выражения, или на базу данных, в которой собраны сведения об HTTP-заголовке User-Agent
. Узнав о том, с каким браузером они имеют дело, они отдают ему материалы, рассчитанные на него.
Тут можно вспомнить два сервиса. Первый — googlefonts.com. Второй — polyfill.io. Сервис Google Fonts предоставляет, для некоего ресурса, различный CSS-код, зависящий от возможностей браузера (давая ссылки на woff2-ресурсы, используя unicode-range
).
Вот результаты пары запросов к Google Fonts, выполненных из разных браузеров.
Результат запроса к Google Fonts, выполненный из Chrome
Результат запроса к Google Fonts, выполненный из IE10
Polyfill.io выдаёт браузеру только те полифиллы, которые ему нужны. Делается это из соображений производительности.
Например, взглянем на то, что произойдёт, если выполнить следующий запрос из разных браузеров: https://polyfill.io/v3/polyfill.js?features=default
В ответ на такой запрос, выполненный из IE10, придёт 34 Кб данных. А ответ на него, выполненный из Chrome, будет пустым.
Злой: некоторые соображения о приватности
Этот пункт последний по порядку, но не по важности. Речь идёт о том, что самостоятельный хостинг сторонних ресурсов на главном домене проекта или на его поддомен способен поставить под угрозу приватность пользователей и негативно сказаться на основном веб-проекте.
Если ваша CDN-система настроена неправильно, всё может кончиться тем, что вы будете отправлять куки вашего домена стороннему сервису. Если на уровне CDN не будет организована правильная фильтрация, то ваши сессионные куки, которыми в обычных условиях нельзя воспользоваться в JavaScript (с атрибутом httponly
), могут быть отправлены на посторонний хост.
Именно это может произойти с трекерами наподобие Eulerian или Criteo. Сторонние трекеры могли устанавливать уникальный идентификатор в куки. Они, если входили в состав материалов сайтов, могли читать идентификатор по своему усмотрению в ходе работы пользователя с разными веб-ресурсами.
В наши дни большинство браузеров включают в себя защиту от подобного поведения трекеров. В результате теперь трекеры используют технологию CNAME Cloaking, маскируясь под собственные скрипты различных проектов. А именно, трекеры предлагают владельцам сайтов добавить в свои настройки CNAME для некоего домена, адрес которого обычно выглядит как случайный набор символов.
Хотя и не рекомендуется делать так, чтобы куки веб-сайта были доступными для всех поддоменов (например — *.website.com), на многих сайтах это делается. В таком случае подобные куки автоматически отправляются замаскированному стороннему трекеру. Как результат — ни о какой приватности уже можно не говорить.
Кроме того, то же самое происходит и с HTTP-заголовками Client-Hints, которые отправляются лишь главному домену, так как они могут быть использованы для создания цифрового отпечатка пользователя. Обратите внимание на то, чтобы используемая вами CDN-служба правильно фильтровала бы подобные заголовки.
Итоги
Если вы собираетесь в скором времени внедрить самостоятельный хостинг сторонних ресурсов — позвольте дать вам несколько советов:
- Хостите у себя свои самые важные JS-библиотеки, шрифты и CSS-файлы. Это снизит риск отказа сайта или снижения его производительности в результате того, что ресурс, жизненно необходимый для работы сайта, оказался недоступным по вине стороннего сервиса.
- Прежде чем кэшировать сторонние ресурсы на CDN, убедитесь в том, что при именовании их файлов используется некая система версионирования, или в том, что вы можете управлять жизненным циклом этих ресурсов, вручную или автоматически сбрасывая кэш CDN при публикации новой версии скрипта.
- Очень внимательно относитесь к настройкам CDN, прокси-сервера, кэша. Это позволит вам не допустить отправки куки-файлов своего проекта или заголовков
Client-Hints
сторонним сервисам.
Уважаемые читатели! Размещаете ли вы на своих серверах чужие материалы, которые чрезвычайно важны для работы ваших проектов?