Bereitstellen von komprimiertem CSS und JavaScript von Amazon CloudFront über S3

194

Ich habe nach Möglichkeiten gesucht, meine Website schneller zu laden, und eine Möglichkeit, die ich untersuchen möchte, besteht darin, Cloudfront stärker zu nutzen.

Da Cloudfront ursprünglich nicht als CDN mit benutzerdefiniertem Ursprung konzipiert war und GZIP nicht unterstützte, habe ich es bisher verwendet, um alle meine Bilder zu hosten, auf die in meinem Site-Code durch ihren Cloudfront-C-Namen verwiesen wird, und mit weit optimiert -Futures Header.

CSS- und Javascript-Dateien werden dagegen auf meinem eigenen Server gehostet, da ich bisher den Eindruck hatte, dass sie nicht über Cloudfront gzippt bereitgestellt werden können und dass der Gewinn durch gzipping (ca. 75 Prozent) diesen überwiegt Verwendung eines CDN (ca. 50 Prozent): Amazon S3 (und damit Cloudfront) unterstützte das standardmäßige Bereitstellen von komprimiertem Inhalt nicht, indem der von Browsern gesendete HTTP Accept-Encoding-Header verwendet wurde, um die Unterstützung für die gzip-Komprimierung anzugeben Daher waren sie nicht in der Lage, Komponenten im laufenden Betrieb zu Gzipen und zu bedienen.

So hatte ich bisher den Eindruck, man müsse zwischen zwei Alternativen wählen:

  1. Verschieben Sie alle Assets in Amazon CloudFront und vergessen Sie GZipping.

  2. Halten Sie die Komponenten selbst gehostet und konfigurieren Sie unseren Server so, dass eingehende Anforderungen erkannt werden und das entsprechende GZipping im laufenden Betrieb durchgeführt wird. Dies habe ich bisher gewählt.

Es gab Problemumgehungen, um dieses Problem zu lösen, aber im Wesentlichen funktionierten diese nicht . [ Link ].

Es scheint, dass Amazon Cloudfront benutzerdefinierten Ursprung unterstützt und dass es jetzt möglich ist, die Standardmethode für die HTTP-Akzeptanzcodierung zum Bereitstellen von komprimiertem Inhalt zu verwenden, wenn Sie einen benutzerdefinierten Ursprung verwenden [ Link ].

Ich konnte die neue Funktion bisher nicht auf meinem Server implementieren. Der Blog-Beitrag, auf den ich oben verlinkt habe und der der einzige ist, bei dem ich die Änderung detailliert gefunden habe, scheint zu implizieren, dass Sie das Zippen nur aktivieren können (Balkenumgehungen, die ich nicht verwenden möchte), wenn Sie sich für einen benutzerdefinierten Ursprung entscheiden Ich möchte lieber nicht: Ich finde es einfacher, die entsprechenden Dateien auf meinem Cloudfront-Server zu hosten und von dort aus auf sie zu verlinken. Trotz sorgfältiger Lektüre der Dokumentation weiß ich nicht:

  • ob die neue Funktion bedeutet, dass die Dateien über einen benutzerdefinierten Ursprung auf meinem eigenen Domänenserver gehostet werden sollen , und wenn ja, mit welchem ​​Code-Setup wird dies erreicht;

  • So konfigurieren Sie die CSS- und Javascript-Header, um sicherzustellen, dass sie über Cloudfront gzippt bereitgestellt werden.

Donald Jenkins
quelle

Antworten:

202

UPDATE: Amazon unterstützt jetzt die gzip-Komprimierung, sodass dies nicht mehr benötigt wird. Amazon Ankündigung

Ursprüngliche Antwort:

Die Antwort ist, die CSS- und JavaScript-Dateien zu komprimieren. Ja, das hast du richtig gelesen.

gzip -9 production.min.css

Dies wird produzieren production.min.css.gz. Entfernen Sie den .gz, laden Sie ihn auf S3 (oder den von Ihnen verwendeten Ursprungsserver) hoch und setzen Sie den Content-EncodingHeader für die Datei explizit auf gzip.

Es ist kein spontanes Gzipping, aber Sie können es sehr einfach in Ihre Build- / Bereitstellungsskripte einbinden. Die Vorteile sind:

  1. Apache benötigt keine CPU, um den Inhalt zu komprimieren, wenn die Datei angefordert wird.
  2. Die Dateien werden mit der höchsten Komprimierungsstufe (vorausgesetzt gzip -9) komprimiert .
  3. Sie liefern die Datei von einem CDN.

Angenommen, Ihre CSS / JavaScript-Dateien sind (a) minimiert und (b) groß genug, um die zum Dekomprimieren auf dem Computer des Benutzers erforderliche CPU zu rechtfertigen, können Sie hier erhebliche Leistungssteigerungen erzielen.

Denken Sie daran: Wenn Sie eine Änderung an einer in CloudFront zwischengespeicherten Datei vornehmen, stellen Sie sicher, dass Sie den Cache nach dieser Art von Änderung ungültig machen.

Skyler Johnson
quelle
37
Nachdem ich Ihren Link gelesen habe, muss ich sagen, dass der Blog-Autor nicht informiert ist. "Wenn der Benutzer jedoch über einen Browser verfügt, der die GZIP-Codierung nicht unterstützt, funktionieren die komprimierten Stylesheets und Javascripts Ihrer Site für diesen Benutzer einfach nicht." Dieser Browser ist wahrscheinlich zu alt, um Ihre Stylesheets und Skriptdateien auszuführen. Diese Benutzer machen einen Bruchteil eines Prozent aus.
Skyler Johnson
3
UPDATE: Ich habe es herausgefunden. Der Grund, warum es nicht angezeigt wurde, war, dass ich vergessen hatte, Content-Type auf text / css zu setzen. Wenn Sie dies tun, ist alles in Ordnung, obwohl Sie aus irgendeinem Grund aus den hier beschriebenen Gründen in S3 keinen "Accept-Encoding: Vary" -Header hinzufügen können (was bei der Google Speed-Bewertung hilfreich wäre): [Link ]. Außerdem habe ich die Cache-Steuerung so eingestellt, dass das Asset zwischengespeichert wird, aber es scheint es nicht zwischenzuspeichern ...
Donald Jenkins
32
Ich habe das gerade über Google gefunden, und es tut mir leid, dass ich sagen muss, dass dies kein so guter Rat ist. Während <1% der Desktop- Browser nicht mit komprimierten Inhalten umgehen können, können dies nicht viele mobile Browser . Wie viele, hängt davon ab, welche Zielgruppe Sie betrachten. Aber die meisten älteren Nokia S40 haben zum Beispiel eine fehlerhafte GZIP-Komprimierung. Der richtige Weg ist ein "benutzerdefinierter Ursprung", der auf einen Apache / IIS-Webserver verweist, der die Inhaltskomprimierung durchführt und die richtigen HTTP-Header bereitstellt. Hier ist ein Blog-Beitrag, der das Wesentliche beschreibt: nomitor.com/blog/2010/11/10/…
Jesper M
14
Wie ist die Situation jetzt, Anfang 2015? Sind die von @JesperMortensen und Simon Peck geposteten Links noch relevant?
ItalyPaleAle
5
Amazon hat im Dezember 2015 die Unterstützung für die GZIP-Komprimierung angekündigt. Daher ist dies jetzt irrelevant. Laden Sie einfach die Basisdatei hoch und es wird funktionieren. aws.amazon.com/blogs/aws/…
Sean
15

Meine Antwort lautet: http://blog.kenweiner.com/2009/08/serving-gzipped-javascript-files-from.html

Aufbauend auf der Antwort von skyler können Sie eine gzip- und eine nicht-gzip-Version von css und js hochladen. Seien Sie vorsichtig beim Benennen und Testen in Safari. Da Safari nicht verarbeiten .css.gzoder .js.gzDateien.

site.jsund site.js.jgzund site.cssund site.gz.css (Sie müssen den content-encodingHeader auf den richtigen MIME-Typ setzen, damit diese richtig funktionieren)

Dann in deine Seite setzen.

<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 ist nur sr_gzipEnabled = true; Dieser Test stellt sicher, dass der Browser mit dem komprimierten Code umgehen kann, und stellt ein Backup bereit, wenn dies nicht möglich ist.

Machen Sie dann etwas Ähnliches in der Fußzeile, vorausgesetzt, alle Ihre js befinden sich in einer Datei und können in die Fußzeile gehen.

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

UPDATE: Amazon unterstützt jetzt die gzip-Komprimierung. Ankündigung, daher wird dies nicht mehr benötigt. Amazon Ankündigung

Sean
quelle
Vielen Dank für diesen Vorschlag. Wenn ich Sie richtig verstehe, sprechen Sie den Fall an, in dem der Browser des Benutzers die komprimierte Datei nicht lesen kann. Dies kann immer noch vorkommen, obwohl es heutzutage nur einen relativ kleinen Prozentsatz der Browser betrifft. Ein möglicher Nachteil dieser Lösung, wenn Sie auf den Link verweisen, den ich in meiner Frage [Link ] gepostet habe, ist, dass Sie Ihre Seite nicht zwischenspeichern können, da dies nur funktioniert, wenn Ihr Code bei jedem Laden eines Benutzers dynamisch ausgeführt wird die Seite (die natürlich meine ist).
Donald Jenkins
@ DonaldJenkins Ich denke, dass die js noch zwischengespeichert werden. Wenn Sie das Skript-Tag im js-Snip erstellen, muss das js noch aufgerufen werden, und ich glaube, wenn es sich im Cache befindet, würde der Browser es von dort aus verwenden.
Sean
2
Die Testseite blog.kosny.com/testpages/safari-gz zeigt an, dass die Warnung "Seien Sie vorsichtig beim Benennen und Testen in Safari. Da Safari nicht mit css.gz oder js.gz umgehen kann" veraltet ist. In Safari 7 unter Mavericks und in Safari unter iOS 7 funktionieren sowohl css.gz als auch js.gz. Ich weiß nicht, wann diese Änderung aufgetreten ist, ich teste nur mit den Geräten, die ich habe.
Garyrob
14

Cloudfront unterstützt Gzipping.

Cloudfront stellt über HTTP 1.0 eine Verbindung zu Ihrem Server her. Standardmäßig stellen einige Webserver, einschließlich Nginx, keine komprimierten Inhalte für HTTP 1.0-Verbindungen bereit. Sie können dies jedoch durch Hinzufügen von:

gzip_http_version 1.0

zu Ihrer Nginx-Konfiguration. Die entsprechende Konfiguration kann für jeden von Ihnen verwendeten Webserver festgelegt werden.

Dies hat den Nebeneffekt, dass Keep-Alive-Verbindungen für HTTP 1.0-Verbindungen nicht funktionieren. Da die Vorteile der Komprimierung jedoch enorm sind, lohnt sich der Kompromiss auf jeden Fall.

Entnommen aus http://www.cdnplanet.com/blog/gzip-nginx-cloudfront/

Bearbeiten

Das Bereitstellen von Inhalten, die im laufenden Betrieb über die Amazon Cloud Front gezippt werden, ist gefährlich und sollte wahrscheinlich nicht durchgeführt werden. Wenn Ihr Webserver den Inhalt komprimiert, legt er grundsätzlich keine Inhaltslänge fest und sendet die Daten stattdessen als Chunked.

Wenn die Verbindung zwischen Cloudfront und Ihrem Server unterbrochen und vorzeitig getrennt wird, speichert Cloudfront das Teilergebnis weiterhin im Cache und dient als zwischengespeicherte Version, bis es abläuft.

Die akzeptierte Antwort, es zuerst auf der Festplatte zu komprimieren und dann die komprimierte Version bereitzustellen, ist eine bessere Idee, da Nginx den Header für die Inhaltslänge festlegen kann und Cloudfront daher abgeschnittene Versionen verwirft.

Danack
quelle
5
-1, Diese Antwort hat nichts mit der Frage zu tun. Nginx! = S3 und Cloudfront
Jonathan
@Danack, gab es aufgrund dieses Problems viele Probleme mit dem Zwischenspeichern von halb abgerufenen Dateien durch Cloudfront? Ich versuche zu verstehen, wie problematisch dies für Sie in der Praxis war.
vornehmsten
1
@poshest Es ist passiert. Es war sehr wenig vorteilhaft, gzipped on the fly zu bedienen (da gzip auf dem Server sowieso so schnell ist), also habe ich es ausgeschaltet, sobald ich es gesehen habe. Beschädigte Daten sind ein viel größeres Problem als eine 200 ms langsame "Zeit bis zum ersten Byte" in den seltenen Fällen, in denen der Inhalt noch nicht im komprimierten Format vorhanden ist.
Danack
Wenn einem Asset eine Content-Length-Eigenschaft im Header fehlt, aber Transfer-Encoding: chunked enthält (wie dies häufig bei komprimierten Assets der Fall ist), speichert CloudFront ein Teil-Asset NICHT zwischen, wenn es keinen terminierenden Chunk erhält. Wenn diese beiden Eigenschaften fehlen, kann ein unvollständiges Asset zwischengespeichert werden. Siehe: docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…
Cody Duval
5

Wir haben kürzlich einige Optimierungen für uSwitch.com vorgenommen, um einige der statischen Assets auf unserer Website zu komprimieren. Obwohl wir dafür einen ganzen Nginx-Proxy eingerichtet haben, habe ich auch eine kleine Heroku-App zusammengestellt, die Proxys zwischen CloudFront und S3 erstellt, um Inhalte zu komprimieren: http://dfl8.co

Da auf öffentlich zugängliche S3-Objekte über eine einfache URL-Struktur zugegriffen werden kann, verwendet http://dfl8.co nur dieselbe Struktur. Dh die folgenden URLs sind äquivalent:

http://pingles-example.s3.amazonaws.com/sample.css
http://pingles-example.dfl8.co/sample.css
http://d1a4f3qx63eykc.cloudfront.net/sample.css
pingles
quelle
5

Gestern hat amazon eine neue Funktion angekündigt. Jetzt können Sie gzip für Ihre Distribution aktivieren.

Es funktioniert mit s3 ohne selbst hinzugefügte .gz-Dateien. Ich habe die neue Funktion heute ausprobiert und sie funktioniert hervorragend. (Sie müssen jedoch Ihre aktuellen Objekte ungültig machen.)

Mehr Info

Chris
quelle
0

Sie können CloudFront so konfigurieren, dass Dateien bestimmter Typen automatisch komprimiert und die komprimierten Dateien bereitgestellt werden.

Siehe AWS Developer Guide

Rafi
quelle
Können Sie weitere Informationen zu Ihrer Lösung hinzufügen (möglicherweise ein Beispiel), um eine bessere Antwort zu erhalten?
Yagami Light