Was ist die Asset-Pipeline?
- Verstehen Sie die 4 Hauptmerkmale der Asset-Pipeline.
- Identifizieren der Asset-Pfade
- Wissen, wie Asset-Manifeste die Verkettung von CSS und JS ermöglichen.
- Vorverarbeitungssprachen wie SASS oder CoffeeScript verwenden
- Asset-Fingerprinting definieren
Gliederung
Lange Zeit haben wir JavaScript und CSS als nachträglichen Einfall bei der Entwicklung von Webanwendungen behandelt. Unser gesamter Asset-Code — Dinge wie Bilder, Stylesheets und JavaScripts — wurde in einem riesigen Ordner namens public
gespeichert und außerhalb des Kontexts unserer Rails-Anwendung bereitgestellt. Als sich das Web entwickelte, machte das keinen Sinn mehr.
Die Asset-Pipeline ist die Rails-Antwort auf die Verwaltung von Stylesheets, JavaScripts und Bildern.
Asset-Pfade
Viele Dateien werden zum Erstellen von Webanwendungen verwendet. Die CSS- und JavaScript-Dateien allein können schwer zu organisieren sein. Welche Ordner erstellen wir? Welche Dateien gehen wohin? Die Asset-Pipeline bietet eine Antwort auf dieses Problem. Wir müssen die Dinge in unserer Anwendung sehr gut organisieren, aber indem wir für jedes Konzept oder jede Codeeinheit separate Dateien und Ordner aufbewahren, haben wir 2 Probleme.
- Woher weiß Rails, wo sich die Dinge befinden? Ist die Kalender-JS-Datei in
app/assets/javascripts/calendar.js
odervendor/javascripts/calendar.js
? - Wir möchten nicht jede Datei separat bereitstellen, da unsere Seite dadurch sehr langsam geladen wird. Für uns ist es sinnvoll, separate kleine Dateien für die Lesbarkeit und Organisation zu verwalten, aber für den Browser möchten wir lieber alle diese kleinen Dateien zusammen zerschlagen und 1 JS-Datei und 1 CSS-Datei laden. Dieser Vorgang wird Verkettung genannt.
Lassen Sie uns über unser erstes Problem sprechen: Woher weiß Rails, wo es zu suchen ist? Die Asset-Pipeline verfügt über ein Konzept namens Asset-Pfade, um dies zu handhaben. Genau wie in BASH, wo wir eine PATH Umgebungsvariable haben, die eine Kombination von Ordnerpfaden ist, ist der Asset-Pfad eine Kombination von Ordnerpfaden, in denen Rails nach Assets suchen kann. Schauen wir uns ein Beispiel an, wie unser Asset-Pfad konfiguriert ist.
Rails.application.config.assets.paths =>
Wenn wir ein Asset in einen dieser Ordner legen, können wir über die URL ‚/assets‘ in unserer Anwendung darauf zugreifen. Wenn Sie über zusätzliche Ordner verfügen, nach denen Rails suchen kann, können Sie die Ordner zum Asset-Pfad hinzufügen. Dies geschieht in der Datei config/initializers/assets.rb
.
Rails.application.config.assets.paths << "New Path"
Wir können Assets überall ablegen, unseren Asset-Pfad konfigurieren und über eine einzige ‚/assets‘-URL darauf zugreifen.
Manifeste und Verkettung
Wie können wir nun Dateien überall ablegen, damit sie in unsere Webseiten aufgenommen werden? Die Asset-Pipeline verwendet eine Manifestdatei, um Rails mitzuteilen, was geladen werden soll. Diese Manifestdatei ist ein zentraler Ort, an dem wir alle CSS- und JS-Dateien auflisten können, die unsere Anwendung benötigt. Dies ist keine Funktion von JS oder CSS, sondern die Asset-Pipeline. Hier ist ein Beispiel dafür, wie unsere JS-Manifestdatei aussieht:
Datei: app/assets/javascripts/application .js
//= require jquery//= require calendar
Wenn Sie die Manifestdatei mit javascript_include_tag
in Ihr Layout aufnehmen, sucht die Asset-Pipeline nach allen im Asset-Pfad aufgeführten Dateien. Beachten Sie, wie wir Kalender benötigen. Diese Datei befindet sich in app/assets/javascripts/calendar.js
, wir haben jedoch nur den Namen und nicht den vollständigen Pfad angegeben. Die Asset-Pipeline durchsucht alle konfigurierten Pfade nach einer Datei mit dem von uns angegebenen Namen.
Nachdem wir nun die Frage der Auffindbarkeit gelöst haben, sprechen wir über die Verkettung. Wie bereits erwähnt, möchten wir unsere Dateien nicht einzeln in den Browser laden. Es ist besser, einen Download durchzuführen als eine Reihe kleiner Downloads von unserem Browser. Die Manifestdateien, die wir in Rails konfigurieren, verketten die darin aufgeführten Dateien automatisch zu einer Datei in der Produktion. Dies ist möglicherweise nicht die beste Option, wenn wir unsere Anwendung entwickeln, da dies das Debuggen erschweren kann. Rails wird jedoch jede Datei separat bereitstellen, wenn wir im Entwicklungsmodus ausgeführt werden. Keine Notwendigkeit, etwas zu tun.
Schließlich werden die verschiedenen Richtlinien, die unsere Asset-Manifeste antreiben, später im Detail behandelt.
Vorverarbeitung
Die Möglichkeit, Dateien zu kombinieren und von einer Reihe vordefinierter Speicherorte in unserer Anwendung zu laden, ist ein großer Vorteil der Asset-Pipeline. Das ist nur der Anfang. Da wir Assets über Rails laden, können wir die Dateien mit gängigen Sprachen wie SCSS zum Schreiben von besserem CSS und Coffeescript für saubereres JS vorverarbeiten. Wenn Sie ein Asset namens Theme erstellen.CSS.scss, Sie weisen die Asset-Pipeline an, die Datei vor dem Bereitstellen des Themas über den SCSS-Präprozessor auszuführen.css an den Browser. Der SCSS-Präprozessor kompiliert die Datei in CSS. Das einzige, was wir tun mussten, war die korrekte Dateierweiterung .scss
für die Datei bereitzustellen, und die Asset-Pipeline weiß, dass sie über den SCSS-Präprozessor ausgeführt wird.
Fingerabdruck
Der letzte Vorteil, über den wir sprechen werden, ist der Fingerabdruck, aber lassen Sie uns zuerst über das Problem sprechen, das uns bei der Lösung hilft. Wenn wir Dateien für den Browser bereitstellen, werden sie wahrscheinlich zwischengespeichert, um zu vermeiden, dass sie in Zukunft erneut heruntergeladen werden. Was ist Caching, könnten Sie fragen?
Zwischenspeichern bedeutet, eine Kopie eines zeitaufwändigen Vorgangs lokal zu speichern, damit Sie den teuren Vorgang nicht erneut wiederholen müssen, wenn die Ein- und Ausgänge genau gleich sind. Caches sind normalerweise Schlüsselwertspeicher, in denen der Wert die Antwort auf die teure Operation ist und der Schlüssel etwas ist, das für dieses Element einzigartig ist. Wenn Sie eine Seite vom Server anfordern und dann dieselbe Seite erneut vom Server anfordern, besteht der schnellste Weg, diese Anforderung zu erfüllen, darin, eine Kopie dessen, was Sie beim letzten Mal erhalten haben, lokal aufzubewahren. Browser cachen viele der Antworten, die sie auf Anfragen erhalten, die sie mithilfe der Header gesendet haben, die mit der Antwort gesendet werden. Die Header sagen dem Browser, wie lange die Seite ‚frisch‘ bleibt, bevor sie abläuft. Sobald die Seite abgelaufen ist, fordert der Browser die Seite erneut an, ihren Cache zu aktualisieren. Wir sagen, dass die schnellste Anfrage die Anfrage ist, die nicht gestellt wird. Es wird auch oft gesagt, dass Cache-Invalidierung eines der beiden harten Probleme in der Informatik ist, also denke sorgfältig nach, wenn du anfängst, Dinge zwischenzuspeichern! Caching spart Bandbreite für uns und bietet einen Geschwindigkeitsschub für den Benutzer. Dies ist großartig, bis Sie die Datei ändern und möchten, dass alle Ihre Benutzer die neue Version anstelle der alten Version erhalten, die sie in ihrem Browser-Cache gespeichert haben. Aber wie lassen wir den Browser wissen, dass wir die Datei geändert haben? Wenn die neue Version denselben Namen wie die alte Version hat, verwendet der Browser weiterhin die alte Datei aus seinem Cache. Wir brauchen eine Möglichkeit, den Dateinamen zu ändern, wenn sich der Inhalt ändert, damit Browser die alte Datei nicht weiter bereitstellen.
Aus dem Rails Guides Primer
„Fingerprinting ist eine Technik, die den Namen eines Dateinamens vom Inhalt der Datei abhängig macht. Wenn sich der Dateiinhalt ändert, wird auch der Dateiname geändert. Für Inhalte, die statisch sind oder selten geändert werden, bietet dies eine einfache Möglichkeit zu erkennen, ob zwei Versionen einer Datei identisch sind, auch über verschiedene Server oder Bereitstellungsdaten hinweg.
Wenn ein Dateiname eindeutig ist und auf seinem Inhalt basiert, können HTTP-Header so eingestellt werden, dass Caches überall (ob bei CDNs, bei ISPs, in Netzwerkgeräten oder in Webbrowsern) aufgefordert werden, ihre eigene Kopie des Inhalts zu behalten. Wenn der Inhalt aktualisiert wird, ändert sich der Fingerabdruck. Dadurch fordern die Remote-Clients eine neue Kopie des Inhalts an. Dies wird als Cache-Busting bezeichnet.
Die Technik, die Sprockets für den Fingerabdruck verwendet, besteht darin, einen Hash des Inhalts an das Ende des Dateinamens anzuhängen. Nehmen wir zum Beispiel eine CSS-Datei mit dem Namen global.css
. Kettenräder fügen den Hash 908e25f4bf641868d8683022a5b62f54
wie folgt am Ende des Dateinamens hinzu:
global-908e25f4bf641868d8683022a5b62f54.css
Wenn Sie eine ältere Version von Rails verwenden (Rails 2.x), bestand die Strategie darin, eine datumsbasierte Abfragezeichenfolge an jedes Asset anzuhängen, das mit einem integrierten Helfer verknüpft ist. Das sah so aus:
global.css?1309495796
Die Abfragezeichenfolgenstrategie hat mehrere Nachteile:
- Nicht alle Caches werden Inhalte zuverlässig zwischenspeichern, bei denen sich der Dateiname nur durch Abfrageparameter unterscheidet.
- Steve Souders empfiehlt „einen Querystring für cachefähige Ressourcen zu vermeiden.“ 5-20% Ihrer Anfragen werden nicht zwischengespeichert. Insbesondere Abfragezeichenfolgen funktionieren bei einigen CDNs zur Cache-Invalidierung überhaupt nicht.
- Der Dateiname kann sich zwischen Knoten in Umgebungen mit mehreren Servern ändern.
- Die Standardabfragezeichenfolge in Rails 2.x basiert auf der Änderungszeit der Dateien. Wenn Assets in einem Cluster bereitgestellt werden, gibt es keine Garantie dafür, dass die Zeitstempel identisch sind, was dazu führt, dass je nachdem, welcher Server die Anforderung verarbeitet, unterschiedliche Werte verwendet werden.
- Zu viel Cache-Ungültigkeit.
- Wenn statische Assets mit jeder neuen Codeversion bereitgestellt werden, ändert sich die mtime (Zeit der letzten Änderung) all dieser Dateien, sodass alle Remote-Clients sie erneut abrufen müssen, auch wenn sich der Inhalt dieser Assets nicht geändert hat.
Fingerprinting behebt all diese Probleme, indem sichergestellt wird, dass Dateinamen basierend auf ihrem Inhalt konsistent sind.
Fingerprinting ist standardmäßig für die Produktion aktiviert und für alle anderen Umgebungen deaktiviert. Sie können es in Ihrer Konfiguration über die Option config.assets.digest
aktivieren oder deaktivieren.“
Fazit
Die Asset-Pipeline ist definitiv komplexer als die Bereitstellung von Assets aus einem öffentlichen Ordner und kann schwer zu debuggen sein. Zu lernen, wie man es benutzt, wird sich auf lange Sicht auszahlen, indem es uns Zeit und Kopfschmerzen spart. Denken Sie nur an all die Probleme, die es für uns löst.
- Asset-Pfade
- Manifeste und Verkettung
- Vorverarbeitung
- Fingerprinting
Schauen Sie sich schließlich unbedingt die Keynote an, in der DHH die Asset-Pipeline vorstellt.