Udostępnianie spakowanego CSS i JavaScript z Amazon CloudFront przez S3

194

Szukałem sposobów na szybsze ładowanie mojej witryny, a jednym ze sposobów, który chciałbym zbadać, jest lepsze wykorzystanie Cloudfront.

Ponieważ Cloudfront pierwotnie nie został zaprojektowany jako CDN niestandardowego pochodzenia i ponieważ nie obsługiwał gzippingu, do tej pory używałem go do hostowania wszystkich moich obrazów, do których odwołuje się ich nazwa Cloudfront w kodzie mojej witryny, i zoptymalizowanych do tej pory przyszłe nagłówki.

Z drugiej strony pliki CSS i javascript są hostowane na moim własnym serwerze, ponieważ do tej pory miałem wrażenie, że nie można ich udostępniać w formacie gzip z Cloudfront i że zysk z gzippingu (około 75 procent) przewyższa to z użycia CDN (około 50 procent): Amazon S3 (a zatem Cloudfront) nie obsługiwał standardowego wyświetlania treści spakowanych gzipem przy użyciu nagłówka HTTP Accept-Encoding wysyłanego przez przeglądarki w celu wskazania ich obsługi kompresji gzip, oraz więc nie byli w stanie zgzipować i podawać komponentów w locie.

Dlatego miałem wrażenie, że do tej pory trzeba było wybierać między dwiema alternatywami:

  1. przenieś wszystkie zasoby do Amazon CloudFront i zapomnij o GZipping;

  2. utrzymuj komponenty na własnym serwerze i skonfiguruj nasz serwer, aby wykrywał przychodzące żądania i odpowiednio wykonywał GZipping w locie, co dotychczas wybrałem.

Tam były obejścia aby rozwiązać ten problem, ale w zasadzie to nie działa . [ link ].

Teraz wygląda na to, że Amazon Cloudfront obsługuje niestandardowe pochodzenie i że można teraz używać standardowej metody kodowania HTTP Accept-Encoding do wyświetlania treści spakowanych gzipem, jeśli używasz niestandardowego źródła [ link ].

Do tej pory nie byłem w stanie wdrożyć nowej funkcji na moim serwerze. Post na blogu, do którego odsyłam powyżej, który jest jedynym, który znalazłem szczegółowo opisujący zmianę, wydaje się sugerować, że możesz włączyć gzipping (obejścia paska, których nie chcę używać), jeśli wybierzesz niestandardowe pochodzenie, które Wolałbym nie: uważam, że łatwiej jest hostować odpowiednie pliki na moim serwerze Cloudfront i stamtąd do nich link. Mimo starannego przeczytania dokumentacji nie wiem:

  • czy nowa funkcja oznacza, że ​​pliki powinny być hostowane na moim własnym serwerze domeny przez niestandardowe pochodzenie, a jeśli tak, to jaki kod to osiągnie;

  • jak skonfigurować nagłówki css i javascript, aby upewnić się, że są one dostarczane w formacie gzip z Cloudfront.

Donald Jenkins
źródło

Odpowiedzi:

202

AKTUALIZACJA: Amazon obsługuje teraz kompresję gzip, więc nie jest to już potrzebne. Ogłoszenie Amazon

Oryginalna odpowiedź:

Odpowiedzią jest gzip plików CSS i JavaScript. Tak, dobrze to przeczytałeś.

gzip -9 production.min.css

To da production.min.css.gz. Usuń plik .gz, prześlij do S3 (lub innego serwera źródłowego, którego używasz) i jawnie ustaw Content-Encodingnagłówek pliku na gzip.

To nie jest gzipowanie w locie, ale można bardzo łatwo owinąć go w skrypty kompilacji / wdrażania. Zalety to:

  1. Apache nie wymaga procesora do gzipowania zawartości, gdy plik jest żądany.
  2. Pliki są gzipowane na najwyższym poziomie kompresji (przy założeniu gzip -9).
  3. Podajesz plik z CDN.

Zakładając, że Twoje pliki CSS / JavaScript są (a) zminimalizowane i (b) wystarczająco duże, aby uzasadnić procesor wymagany do dekompresji na komputerze użytkownika, możesz uzyskać znaczny wzrost wydajności tutaj.

Pamiętaj tylko: jeśli dokonasz zmiany w pliku buforowanym w CloudFront, upewnij się, że unieważniłeś pamięć podręczną po dokonaniu tego typu zmiany.

Skyler Johnson
źródło
37
Po przeczytaniu linku muszę powiedzieć, że autor bloga jest niedoinformowany. „Jednak jeśli użytkownik ma przeglądarkę, która nie obsługuje kodowania gzip, spakowane arkusze stylów i skrypty javascript po prostu nie będą działać dla tego użytkownika”. Ta przeglądarka prawdopodobnie i tak byłaby za stara, aby uruchomić arkusze stylów i pliki skryptów. Ci użytkownicy stanowią ułamek procenta.
Skyler Johnson
3
AKTUALIZACJA: Rozpracowałem to. Powodem, dla którego nie był wyświetlany, było to, że zapomniałem ustawić Content-Type na text / css. Jeśli to zrobisz, nic ci nie jest, chociaż z jakiegoś powodu wydaje się, że nie możesz dodać nagłówka „Accept-Encoding: Vary” w S3 (co pomogłoby w ocenie prędkości Google) z powodów opisanych tutaj: [link ]. Ponadto ustawiłem Cache-control, aby buforował zasób, ale nie wydaje się, żeby buforował go ...
Donald Jenkins
32
Właśnie znalazłem to za pośrednictwem Google i przykro mi, że muszę powiedzieć, że nie jest to dobra rada. Podczas gdy <1% przeglądarek komputerowych nie obsługuje treści spakowanych gzipem, wiele przeglądarek mobilnych nie. Ile zależy od grupy docelowej, na którą patrzysz; ale większość starszych telefonów Nokia S40 ma na przykład wadliwą kompresję gzip. Właściwym sposobem jest „Niestandardowe pochodzenie”, które wskazuje na serwer Apache / IIS, który kompresuje zawartość i obsługuje odpowiednie nagłówki HTTP. Oto jeden post na blogu, który opisuje sedno sprawy
Jesper M
14
Jaka jest teraz sytuacja na początku 2015 r.? Czy linki zamieszczone przez @JesperMortensen i Simon Peck są nadal aktualne?
PaleAle
5
Amazon ogłosił wsparcie dla kompresji gzip w grudniu 2015 roku, więc nie ma to już znaczenia, po prostu prześlij plik podstawowy i będzie działać. aws.amazon.com/blogs/aws/…
Sean
15

Moja odpowiedź jest taka: http://blog.kenweiner.com/2009/08/serving-gzipped-javascript-files-from.html

Opierając się na odpowiedzi skylera, możesz wgrać css i js w wersji gzip i non-gzip. Bądź ostrożny, nazywając i testując w Safari. Ponieważ safari nie obsługuje .css.gzani .js.gzplików.

site.jsi site.js.jgzoraz site.cssi site.gz.css (musisz ustawićcontent-encoding nagłówek do odpowiedniego typu MIME, aby uzyskać te służyć prawo)

Następnie na swojej stronie umieść.

<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 jest po prostu sr_gzipEnabled = true; Ten test sprawdza, czy przeglądarka może obsłużyć spakowany kod i zapewnić kopię zapasową, jeśli nie mogą.

Następnie zrób coś podobnego w stopce, zakładając, że wszystkie twoje pliki są w jednym pliku i mogą iść w stopce.

<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> 

AKTUALIZACJA: Amazon obsługuje teraz kompresję gzip. Ogłoszenie, więc nie jest już potrzebne. Ogłoszenie Amazon

Sean
źródło
bardzo dziękuję za tę sugestię. Jeśli dobrze cię rozumiem, zajmujesz się przypadkiem, w którym przeglądarka użytkownika nie jest w stanie odczytać pliku spakowanego gzipem, co może nadal występować, chociaż obecnie dotyczy dość niewielkiego odsetka przeglądarek. Jedną z możliwych wad tego rozwiązania, jeśli odwołujesz się do linku, który zamieściłem w moim pytaniu [link ], jest to, że oznacza to, że nie możesz buforować strony, ponieważ będzie działać tylko wtedy, gdy kod będzie uruchamiany dynamicznie za każdym razem, gdy użytkownik ładuje się strona (która oczywiście jest moja).
Donald Jenkins,
@DonaldJenkins Myślę, że js nadal będzie buforowany. Kiedy budujesz tag skryptu w wycinku js, js wciąż musi zostać wywołany i uważam, że jeśli jest w pamięci podręcznej, przeglądarka użyje go stamtąd.
Sean
2
Strona testowa blog.kosny.com/testpages/safari-gz wskazuje, że ostrzeżenie „Ostrożnie nazwij i przetestuj w Safari. Ponieważ safari nie obsługuje css.gz ani js.gz” jest nieaktualne. W Safari 7 na Mavericks i Safari na iOS 7 działają zarówno css.gz, jak i js.gz. Nie wiem, kiedy nastąpiła ta zmiana, testuję tylko na urządzeniach, które mam.
garyrob
14

Cloudfront obsługuje gzipping.

Cloudfront łączy się z twoim serwerem przez HTTP 1.0. Domyślnie niektóre serwery WWW, w tym nginx, nie wyświetlają treści spakowanych gzipem w połączeniach HTTP 1.0, ale możesz to zrobić, dodając:

gzip_http_version 1.0

do twojej konfiguracji nginx. Odpowiednią konfigurację można ustawić dla dowolnego używanego serwera WWW.

Ma to efekt uboczny polegający na tym, że połączenia utrzymujące aktywność nie działają w przypadku połączeń HTTP 1.0, ale ponieważ korzyści z kompresji są ogromne, zdecydowanie warto z tego skorzystać.

Zaczerpnięte z http://www.cdnplanet.com/blog/gzip-nginx-cloudfront/

Edytować

Udostępnianie treści, które są zgzipowane w locie przez chmurę Amazon, jest niebezpieczne i prawdopodobnie nie powinno się tego robić. Zasadniczo, jeśli serwer WWW zgrywa zawartość, nie ustawi długości treści i zamiast tego wyśle ​​dane jako porcje.

Jeśli połączenie między Cloudfront a twoim serwerem zostanie przerwane i przedwcześnie zerwane, Cloudfront nadal buforuje częściowy wynik i służy jako wersja buforowana aż do wygaśnięcia.

Przyjęta odpowiedź, że najpierw zgolisz go na dysku, a następnie udostępnisz wersję gzipped, jest lepszym pomysłem, ponieważ Nginx będzie mógł ustawić nagłówek Content-Length, a więc Cloudfront odrzuci okrojone wersje.

Danack
źródło
5
-1, ta odpowiedź nie ma nic wspólnego z pytaniem. Nginx! = S3 i Cloudfront
Jonathan
@Danack, czy napotkałeś wiele problemów z buforowaniem przez Cloudfront częściowo pobranych plików z powodu tego problemu? Próbuję zrozumieć, w jakim stopniu był to dla ciebie problem w praktyce.
najszerszy
1
@poshest To się stało. Udostępnianie gzipa w locie przyniosło bardzo niewielkie korzyści (ponieważ gzip i tak jest tak szybki na serwerze), więc wyłączyłem go, gdy tylko go zobaczyłem. Uszkodzone dane są znacznie większym problemem niż „czas do pierwszego bajtu” spowolnienia o 200 ms w rzadkich przypadkach, gdy treść nie istnieje jeszcze w formacie gzip.
Danack
Jeśli w zasobie brakuje właściwości Content-Length w nagłówku, ale zawiera kodowanie transferowe: porcjami (jak to często bywa z zasobami spakowanymi gzip), CloudFront NIE buforuje częściowego zasobu, jeśli nie otrzyma porcji kończącej. Jeśli brakuje obu tych właściwości, możliwe jest buforowanie niekompletnego zasobu. Zobacz: docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…
Cody Duval
5

Niedawno dokonaliśmy kilku optymalizacji dla uSwitch.com w celu skompresowania niektórych zasobów statycznych na naszej stronie. Chociaż skonfigurowaliśmy do tego celu cały serwer proxy Nginx, stworzyłem również małą aplikację Heroku, która pośredniczy między CloudFront i S3 w celu kompresji zawartości: http://dfl8.co

Biorąc pod uwagę publicznie dostępne obiekty S3, można uzyskać dostęp za pomocą prostej struktury URL, http://dfl8.co po prostu używa tej samej struktury. Czyli następujące adresy URL są równoważne:

http://pingles-example.s3.amazonaws.com/sample.css
http://pingles-example.dfl8.co/sample.css
http://d1a4f3qx63eykc.cloudfront.net/sample.css
pingle
źródło
5

Wczoraj Amazon ogłosił nową funkcję, teraz możesz włączyć gzip w swojej dystrybucji.

Działa z s3 bez dodanych plików .gz, wypróbowałem dziś nową funkcję i działa świetnie. (musisz jednak unieważnić twoje obecne obiekty)

Więcej informacji

Chris
źródło
0

Możesz skonfigurować CloudFront, aby automatycznie kompresował pliki niektórych typów i obsługiwał skompresowane pliki.

Zobacz Podręcznik programisty AWS

Rafi
źródło
Czy możesz dodać więcej informacji o swoim rozwiązaniu (być może przykład), aby była to lepsza odpowiedź.
Yagami Light,