Обслуживание сжатых CSS и JavaScript из Amazon CloudFront через S3

194

Я искал способы ускорить загрузку моего сайта, и один из способов, который я хотел бы изучить, - это более широкое использование Cloudfront.

Из-за того, что Cloudfront изначально не был разработан как CDN пользовательского происхождения, и поскольку он не поддерживал gzipping, я до сих пор использовал его для размещения всех моих изображений, на которые ссылается их имя Cloudfront cname в коде моего сайта, и оптимизировал для фьючерсные заголовки.

Файлы CSS и javascript, с другой стороны, размещены на моем собственном сервере, потому что до сих пор у меня сложилось впечатление, что их нельзя обслуживать в gzip-архиве из Cloudfront, и что выгода от gzipping (около 75%) превышает от использования CDN (около 50%): Amazon S3 (и, следовательно, Cloudfront) не поддерживал стандартную обработку gzip-содержимого с помощью заголовка HTTP Accept-Encoding, отправляемого браузерами для указания их поддержки сжатия gzip, и поэтому они не могли Gzip и обслуживать компоненты на лету.

Таким образом, до сих пор у меня сложилось впечатление, что нужно выбирать между двумя альтернативами:

  1. перенести все активы в Amazon CloudFront и забыть о GZipping;

  2. оставляйте компоненты размещенными самостоятельно и настраивайте наш сервер для обнаружения входящих запросов и выполнения GZipping на лету в зависимости от ситуации, что я и решил сделать до сих пор.

Там были обходные пути , чтобы решить эту проблему, но по существу они не работают . [ ссылка ].

Похоже, что Amazon Cloudfront поддерживает пользовательское происхождение, и теперь можно использовать стандартный метод HTTP Accept-Encoding для обслуживания сжатого содержимого, если вы используете пользовательское происхождение [ ссылка ].

До сих пор я не смог реализовать новую функцию на моем сервере. Сообщение в блоге, на которое я ссылался выше, - единственное, в котором я нашел подробное описание изменения, похоже, подразумевает, что вы можете включить gzipping (обходные пути, которые я не хочу использовать), если вы выбираете пользовательское происхождение, которое Я бы предпочел этого не делать: я считаю, что проще размещать соответствующие файлы на моем сервере Cloudfront и ссылаться на них оттуда. Несмотря на тщательное чтение документации, я не знаю:

  • означает ли новая функция, что файлы должны быть размещены на моем собственном доменном сервере через пользовательское происхождение, и если да, то какая настройка кода достигнет этого;

  • как настроить заголовки css и javascript, чтобы обеспечить их доставку из Cloudfront.

Дональд Дженкинс
источник

Ответы:

202

ОБНОВЛЕНИЕ: Amazon теперь поддерживает сжатие GZIP, так что это больше не нужно. Амазонское Объявление

Оригинальный ответ:

Ответ заключается в том, чтобы сжать файлы CSS и JavaScript. Да, вы правильно прочитали.

gzip -9 production.min.css

Это будет производить production.min.css.gz. Удалите .gz, загрузите на S3 (или любой другой сервер происхождения, который вы используете) и явно установите Content-Encodingзаголовок для файла gzip.

Это не на лету, но вы можете легко обернуть его в свои сценарии сборки / развертывания. Преимущества:

  1. Apache не требует CPU для сжатия содержимого при запросе файла.
  2. Файлы сжаты с максимальным уровнем сжатия (при условии gzip -9).
  3. Вы подаете файл из CDN.

Предполагая, что ваши файлы CSS / JavaScript (а) минимизированы и (б) достаточно велики, чтобы оправдать использование ЦП, необходимое для распаковки на компьютере пользователя, вы можете получить здесь значительный прирост производительности.

Просто помните: если вы вносите изменения в файл, который кэшируется в CloudFront, убедитесь, что вы сделали недействительным кеш после внесения изменений такого типа.

Скайлер Джонсон
источник
37
Прочитав вашу ссылку, я должен сказать, что автор блога не информирован. «Однако, если у пользователя есть браузер, который не поддерживает кодировку gzip, сжатые таблицы стилей и javascripts вашего сайта просто не будут работать для этого пользователя». Этот браузер, скорее всего, будет слишком стар для запуска ваших таблиц стилей и файлов сценариев. Эти пользователи составляют долю процента.
Скайлер Джонсон
3
ОБНОВЛЕНИЕ: я решил это. Причина, по которой он не отображался, заключалась в том, что я забыл установить Content-Type на text / css. Если вы это сделаете, у вас все хорошо, хотя по какой-то причине кажется, что вы не можете добавить заголовок «Accept-Encoding: Vary» в S3 (который поможет с рейтингом Google Speed) по причинам, описанным здесь: [ссылка ]. Кроме того, я установил Cache-control для кэширования актива, но, похоже, он его не кэширует ...
Дональд Дженкинс
32
Просто нашел это через Google, и я сожалею, что должен сказать, что это не очень хороший совет. В то время как <1% браузеров настольных компьютеров не могут обрабатывать сжатый контент, довольно много мобильных браузеров не могут. Сколько зависит от того, на какую целевую аудиторию вы смотрите; но большинство старых Nokia S40, например, имеют глючное сжатие gzip. Надлежащим способом является «Custom Origin», который указывает на веб-сервер Apache / IIS, который выполняет сжатие содержимого и обслуживает правильные заголовки HTTP. Вот одно сообщение в блоге, которое описывает суть этого: nomitor.com/blog/2010/11/10/…
Jesper M
14
Как обстоят дела сейчас, в начале 2015 года? Актуальны ли ссылки, опубликованные @JesperMortensen и Саймоном Пеком?
ItalyPaleAle
5
Amazon объявила о поддержке сжатия gzip в декабре 2015 года, так что теперь это не имеет значения, просто загрузите основной файл, и он будет работать. aws.amazon.com/blogs/aws/…
Шон
15

Мой ответ на это: http://blog.kenweiner.com/2009/08/serving-gzipped-javascript-files-from.html

Построив ответ Скайлера, вы можете загрузить версии css и js для gzip и non-gzip. Будьте осторожны с именами и тестируйте в Safari. Потому что сафари не справится .css.gzили.js.gz файлы.

site.jsи site.js.jgzи site.cssи site.gz.css (вам нужно установить content-encodingзаголовок на правильный тип MIME, чтобы они работали правильно)

Тогда в вашей странице положить.

<script type="text/javascript">var sr_gzipEnabled = false;</script> 
<script type="text/javascript" src="http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr.gzipcheck.js.jgz"></script> 

<noscript> 
  <link type="text/css" rel="stylesheet" href="http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css">
</noscript> 
<script type="text/javascript"> 
(function () {
    var sr_css_file = 'http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css';
    if (sr_gzipEnabled) {
      sr_css_file = 'http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css.gz';
    }

    var head = document.getElementsByTagName("head")[0];
    if (head) {
        var scriptStyles = document.createElement("link");
        scriptStyles.rel = "stylesheet";
        scriptStyles.type = "text/css";
        scriptStyles.href = sr_css_file;
        head.appendChild(scriptStyles);
        //alert('adding css to header:'+sr_css_file);
     }
}());
</script> 

просто gzipcheck.js.jgz sr_gzipEnabled = true; тест Он проверяет, может ли браузер обрабатывать сжатый код и предоставляет резервную копию, если не может.

Затем сделайте что-то похожее в нижнем колонтитуле, предполагая, что все ваши js находятся в одном файле и могут идти в нижнем колонтитуле.

<div id="sr_js"></div> 
<script type="text/javascript"> 
(function () {
    var sr_js_file = 'http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr-br-min.js';
    if (sr_gzipEnabled) {
       sr_js_file = 'http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr-br-min.js.jgz';
    }
    var sr_script_tag = document.getElementById("sr_js");         
    if (sr_script_tag) {
    var scriptStyles = document.createElement("script");
    scriptStyles.type = "text/javascript";
    scriptStyles.src = sr_js_file;
    sr_script_tag.appendChild(scriptStyles);
    //alert('adding js to footer:'+sr_js_file);
    }
}());
</script> 

ОБНОВЛЕНИЕ: Amazon теперь поддерживает сжатие gzip. Объявление, так что это больше не нужно. Амазонское Объявление

Шон
источник
Большое спасибо за это предложение. Если я вас правильно понимаю, вы имеете дело со случаем, когда браузер пользователя не может прочитать gzip-файл, который все еще может возникнуть, хотя в настоящее время это касается довольно небольшого процента браузеров. Одним из возможных недостатков этого решения, если вы ссылаетесь на ссылку, которую я разместил в моем вопросе [ссылка ], является то, что это означает, что вы не можете кэшировать свою страницу, поскольку оно будет работать, только если ваш код запускается динамически каждый раз, когда пользователь загружает страница (которая, конечно, моя).
Дональд Дженкинс
@DonaldJenkins Я думаю, что JS все еще будет кэшироваться. Когда вы создаете тег script в js snip, js все равно нужно вызывать, и я считаю, что если он находится в кеше, браузер будет использовать его оттуда.
Шон
2
На тестовой странице blog.kosny.com/testpages/safari-gz указано, что предупреждение «Будьте осторожны с именами и тестами в Safari. Потому что safari не будет обрабатывать css.gz или js.gz» устарело. В Safari 7 на Mavericks и в Safari на iOS 7 работают css.gz и js.gz. Я не знаю, когда произошло это изменение, я тестирую только те устройства, которые у меня есть.
Гарироб
14

Cloudfront поддерживает gzipping.

Cloudfront подключается к вашему серверу через HTTP 1.0. По умолчанию некоторые веб-серверы, в том числе nginx, не подают сжатый контент на соединения HTTP 1.0, но вы можете указать это, добавив:

gzip_http_version 1.0

в ваш конфиг nginx. Эквивалентная конфигурация может быть установлена ​​для любого веб-сервера, который вы используете.

Это имеет побочный эффект, заключающийся в том, что поддерживающие соединения не работают для соединений HTTP 1.0, но поскольку преимущества сжатия огромны, это определенно стоит компромисса.

Взято с http://www.cdnplanet.com/blog/gzip-nginx-cloudfront/

редактировать

Подача контента, который распространяется на лету через облачный фронт Amazon, опасна и, вероятно, не должна выполняться. По сути, если ваш веб-сервер распаковывает содержимое, он не устанавливает Content-Length и вместо этого отправляет данные в виде фрагментов.

Если соединение между Cloudfront и вашим сервером прервано и преждевременно разорвано, Cloudfront все еще кэширует частичный результат и использует его в качестве кэшированной версии до истечения срока его действия.

Принятый ответ - сначала распаковать его на диск, а затем отправить версию в сжатом виде - это лучшая идея, поскольку Nginx сможет установить заголовок Content-Length, а Cloudfront откажется от усеченных версий.

Danack
источник
5
-1 Этот ответ не имеет ничего общего с вопросом. Nginx! = S3 и Cloudfront
Джонатан
@ Данак, из-за этой проблемы вы сталкивались с большим количеством проблем с кэшированием наполовину полученных файлов Cloudfront? Я пытаюсь понять, насколько это сложно для тебя на практике.
шикарная
1
@poshest Это случилось. Было очень мало пользы от gzip на лету (так как gzip так быстро работает на сервере), поэтому я отключил его, как только увидел, что это происходит. Поврежденные данные представляют собой гораздо большую проблему, чем медленное «время до первого байта» на 200 мс в тех редких случаях, когда контент еще не существует в формате GZIP.
Данак
Если у актива отсутствует свойство Content-Length в заголовке, но есть Transfer-Encoding: chunked (как это часто бывает с gzip-активами), CloudFront НЕ будет кэшировать частичный актив, если он не получит завершающий блок. Если в нем отсутствуют оба этих свойства, возможно кэширование неполного актива. См .: docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…
Коди Дюваль,
5

Недавно мы сделали несколько оптимизаций для uSwitch.com, чтобы сжать некоторые статические ресурсы на нашем сайте. Хотя для этого мы настроили целый прокси-сервер nginx, я также собрал небольшое приложение Heroku, которое проксирует между CloudFront и S3 для сжатия контента: http://dfl8.co

Если к общедоступным объектам S3 можно получить доступ с помощью простой структуры URL, http://dfl8.co просто использует ту же структуру. Т.е. следующие URL-адреса эквивалентны:

http://pingles-example.s3.amazonaws.com/sample.css
http://pingles-example.dfl8.co/sample.css
http://d1a4f3qx63eykc.cloudfront.net/sample.css
pingles
источник
5

Вчера Amazon объявил о новой функции, теперь вы можете включить gzip в вашем дистрибутиве.

Он работает с s3 без добавления .gz файлов самостоятельно, сегодня я попробовал новую функцию, и она отлично работает. (необходимо аннулировать ваши текущие объекты, хотя)

Больше информации

Крис
источник
0

Вы можете настроить CloudFront для автоматического сжатия файлов определенных типов и обслуживания сжатых файлов.

См. Руководство для разработчиков AWS

Рафи
источник
Можете ли вы добавить больше информации о вашем решении (может быть, в качестве примера), чтобы сделать его лучшим ответом.
Ягами Лайт