config.assets.compile = true in der Rails-Produktion, warum nicht?

184

Die von installierte Standard-Rails-App rails newbefindet sich config.assets.compile = falsein der Produktion.

Die übliche Vorgehensweise besteht darin, sie rake assets:precompilevor der Bereitstellung Ihrer App auszuführen , um sicherzustellen, dass alle Asset-Pipeline-Assets kompiliert werden.

Was passiert also, wenn ich config.assets.compile = truein Produktion gehe?

Ich muss nicht precompilemehr rennen . Ich glaube , dass ein Asset zum ersten Mal angefordert wird, wenn es angefordert wird. Dies ist beim ersten Mal ein Leistungseinbruch (und dies bedeutet, dass Sie in der Regel eine js-Laufzeit in der Produktion benötigen, um dies zu tun). Abgesehen von diesen Nachteilen denke ich, dass nach dem trägen Kompilieren des Assets alle nachfolgenden Zugriffe auf dieses Asset keinen Leistungseinbruch haben. Die Leistung der App ist genau die gleiche wie bei vorkompilierten Assets nach dieser ersten faulen Kompilierung mit dem ersten Treffer. Ist das wahr?

Fehlt mir etwas? Gibt es noch andere Gründe, nicht config.assets.compile = truein Produktion zu gehen? Wenn ich eine JS-Laufzeit in der Produktion habe und bereit bin, den Kompromiss zwischen Leistungseinbußen beim ersten Zugriff auf ein Asset einzugehen, um nicht ausgeführt zu werden precompile, ist dies sinnvoll?

jrochkind
quelle
1
Warnung: Ältere Versionen von Kettenrädern enthalten einen Fehler. Wenn config.assets.compile auf true konfiguriert ist, besteht das Risiko einer Sicherheitsanfälligkeit in Bezug auf die Verzeichnisübertragung ( blog.heroku.com/rails-asset-pipeline-vulnerability )
Mauro
Genau so soll Stackoverflow funktionieren. Eine gut geschriebene Frage und eine gut geschriebene Antwort. Ich liebe euch beide op und @ richard-hulse.
schmijos

Antworten:

258

Ich habe diesen Teil des Leitfadens geschrieben.

Sie möchten definitiv nicht live in der Produktion kompilieren.

Wenn Sie kompiliert haben, geschieht Folgendes:

Jede Anforderung für eine Datei in / Assets wird an Sprockets übergeben. Bei der ersten Anforderung für jedes einzelne Asset wird es kompiliert und in dem Rache zwischengespeichert, der von Rails für den Cache verwendet wird (normalerweise im Dateisystem).

Bei nachfolgenden Anforderungen empfängt Sprockets die Anforderung und muss den Dateinamen mit dem Fingerabdruck nachschlagen, überprüfen, ob die Datei (Bild) oder Dateien (CSS und JS), aus denen das Asset besteht, nicht geändert wurden, und wenn eine zwischengespeicherte Version vorhanden ist, wird dies bereitgestellt.

Das ist alles im Assets-Ordner und in allen Lieferanten- / Assets-Ordnern, die von Plugins verwendet werden.

Das ist viel Aufwand, da der Code ehrlich gesagt nicht auf Geschwindigkeit optimiert ist.

Dies wirkt sich darauf aus, wie schnell das Asset über die Leitung zum Client geleitet wird, und wirkt sich negativ auf die Ladezeiten Ihrer Website aus.

Vergleichen Sie mit der Standardeinstellung:

Wenn Assets vorkompiliert werden und die Kompilierung deaktiviert ist, werden Assets kompiliert und mit einem Fingerabdruck versehen public/assets. Sprockets gibt eine Zuordnungstabelle der einfachen Dateinamen mit Fingerabdruck an Rails zurück, und Rails schreibt diese in das Dateisystem. Die Manifestdatei (YML in Rails 3 oder JSON mit einem zufälligen Namen in Rails 4) wird beim Start von Rails in den Speicher geladen und zur Verwendung durch die Asset-Helper-Methoden zwischengespeichert.

Dies macht die Generierung von Seiten mit den richtigen Fingerabdruck-Assets sehr schnell, und die Bereitstellung der Dateien selbst erfolgt schnell vom Webserver aus dem Dateisystem. Beides dramatisch schneller als Live-Kompilierung.

Um den maximalen Vorteil der Pipeline und des Fingerabdrucks zu erzielen, müssen Sie auf Ihrem Webserver Header für die Zukunft festlegen und die GZIP-Komprimierung für JS- und CSS-Dateien aktivieren. Sprockets schreibt komprimierte Versionen von Assets, die Sie für die Verwendung auf Ihrem Server festlegen können, ohne dass dies für jede Anforderung erforderlich ist.

Dadurch werden Assets so schnell wie möglich und in der kleinstmöglichen Größe an den Client gesendet, wodurch die clientseitige Anzeige der Seiten beschleunigt und Anforderungen (mit Header in ferner Zukunft) reduziert werden.

Wenn Sie also live kompilieren, ist dies:

  1. Sehr langsam
  2. Fehlt die Komprimierung
  3. Beeinflusst die Renderzeit von Seiten

Gegen

  1. So schnell wie möglich
  2. Komprimiert
  3. Entfernen Sie die vom Server belauschte Komprimierung (optional).
  4. Minimieren Sie die Renderzeit von Seiten.

Bearbeiten: (Antwort auf nachfolgenden Kommentar)

Die Pipeline könnte bei der ersten Anforderung geändert werden, um vorkompiliert zu werden, aber es gibt einige wichtige Hindernisse dafür. Das erste ist, dass es eine Nachschlagetabelle für Namen mit Fingerabdrücken geben muss, oder die Hilfsmethoden sind zu langsam. Unter einem Compile-on-Demand-Szenario müsste es eine Möglichkeit geben, an die Nachschlagetabelle anzuhängen, wenn jedes neue Asset kompiliert oder angefordert wird.

Außerdem müsste jemand den Preis für eine langsame Lieferung von Vermögenswerten für einen unbekannten Zeitraum zahlen, bis alle Vermögenswerte zusammengestellt und vorhanden sind.

Die Standardeinstellung, bei der der Preis für die Kompilierung alles gleichzeitig offline bezahlt wird, wirkt sich nicht auf die öffentlichen Besucher aus und stellt sicher, dass alles funktioniert, bevor die Dinge live gehen.

Der Deal-Breaker ist, dass es Produktionssystemen viel Komplexität verleiht.

[Bearbeiten, Juni 2015] Wenn Sie dies lesen, weil Sie nach einer Lösung für langsame Kompilierungszeiten während einer Bereitstellung suchen, können Sie die Assets lokal vorkompilieren. Informationen hierzu finden Sie im Asset-Pipeline-Handbuch . Auf diese Weise können Sie nur dann lokal vorkompilieren, wenn eine Änderung vorliegt, diese festschreiben und dann eine schnelle Bereitstellung ohne Vorkompilierungsphase durchführen.

Richard Hulse
quelle
1
Danke, ich habe deine Antwort akzeptiert. Aber jetzt ist meine Frage, okay, es tut es jetzt nicht, aber denken Sie, dass die Asset Pipeline eine Funktion haben könnte , bei der sie auf erste Anfrage träge kompiliert wird und genau wie vorkompiliert wird, einschließlich Schreiben in ./public und Aktualisieren das Fingerabdruck-Manifest?
Jrochkind
Siehe oben. Ist das ein Problem, weil Capistrano bei Ihnen nicht funktioniert?
Richard Hulse
Ich benutze Capistrano nicht. Ich habe es vorher nicht gebraucht, die zusätzliche Komplexität hat sich nicht gelohnt. Vielleicht ist die Asset-Pipeline der Strohhalm, der die Kamele zurückbricht und benötigt. Ihrer Meinung nach ist es unmöglich, Rails-Bereitstellungen mit Asset-Pipeline ohne Capistrano oder ähnliches zu verwalten? Es ist eine Schande, für einfache Setups war es früher kein großes Problem, es von Hand zu machen.
Jrochkind
Sie brauchen Capistrano für Rails 3.1 wirklich. Die Assets werden in einem neuen öffentlichen Verzeichnis kompiliert, während Ihre alte App noch ausgeführt wird. Nach Abschluss der Kompilierung wird die neue Version verknüpft und der Server automatisch neu gestartet.
Richard Hulse
"Um den maximalen Vorteil der Pipeline und des Fingerabdrucks zu erzielen, müssen Sie auf Ihrem Webserver Header für die Zukunft festlegen und die GZIP-Komprimierung für JS- und CSS-Dateien aktivieren." - Geben Sie bitte einige Anweisungen oder Links dazu an Dies?
Isaac Betesh
7

Weniger Aufwand beim Vorkompilieren.

Precompile everything initially with these settings in production.rb
# Precompile *all* assets, except those that start with underscore
config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/

Sie können dann einfach Bilder und Stylesheets als "/assets/stylesheet.css" in * .html.erb oder "/assets/web.png" verwenden.

dbKooper
quelle
6

Für alle, die Heroku verwenden:

Wenn Sie auf Herkou bereitstellen, wird die Vorkompilierung während der Bereitstellung automatisch für Sie durchgeführt, wenn kompilierte Assets nicht enthalten sind (dh public/assetsnicht festgeschrieben sind), sodass config.assets.compile = truedie vorkompilierten Assets nicht erforderlich sind oder festgeschrieben werden müssen .

Herokus Dokumente sind hier . Ein CDN wird empfohlen, um die Last auf der Dyno-Ressource zu entfernen.

William Denniss
quelle
1

Dies ist auch nach dem ersten Treffer nicht dasselbe wie Vorkompilieren: Da die Dateien nicht in das Dateisystem geschrieben wurden, können sie nicht direkt vom Webserver bereitgestellt werden. Es wird immer etwas Ruby-Code beteiligt sein, selbst wenn er nur einen Cache-Eintrag liest.

Frederick Cheung
quelle
Hmm, ich dachte, dass mit precompile=true, die kompilierten Assets in das Dateisystem geschrieben werden würden. Bist du sicher? Lassen Sie mich überprüfen ...
jrochkind
1
Bah, ich glaube , du hast Recht - sie in das Dateisystem geschrieben werden, aber es sieht aus wie in tmp/cacheanstatt public/assets, so keinen Platz , dass der Webserver sehen können, sie gehen nach wie vor von den Schienen bedient werden App nicht der Webserver. bla. ist das richtig, denkst du?
Jrochkind
Richtig. Es wird nicht so schnell sein, als würde der Webserver sie direkt abholen. Könnte keine Rolle spielen, wenn Sie eine CDN wie Cloudfront vor Ihre App stellen
Frederick Cheung
1

einstellen config.asset.compile = false

Fügen Sie Ihrem Gemfile hinzu

group :assets do gem 'turbo-sprockets-rails3' end

Installieren Sie das Bundle

Lauf rake assets:precompile

Starten Sie dann Ihren Server

Mohammed Saleem
quelle
Soweit ich die config.asset.compile = true in production.rbDatei eingestellt habe, wird kein Pre-Comple-Mechanismus hinzugefügt. Aus diesem Grund dauert das Laden der Seite bei jedem Start des Servers zu lange (wenn die Anforderung sowohl die Verarbeitung der Anforderung als auch das Kompilieren von Assets betrifft). Jetzt habe ich turbo-sprockets-rails3in Gemfile aufgenommen und den Befehl ausgeführt, rake assets:precompileder die Assets zuvor kompiliert. Jetzt setze config.asset.compile = false in production.rbund starte ich den Server, die Seite wird ohne Verzögerung geladen. (Nur Bearbeitung der Anfrage ohne Zusammenstellung von Vermögenswerten)
Mohammed Saleem
2
Erwähnenswert ist, dass dies turbo-sprockets-rails3nur für Ruby 3
Andre Figueiredo
0

Aus dem offiziellen Leitfaden :

Bei der ersten Anforderung werden die Assets wie in der obigen Entwicklung beschrieben kompiliert und zwischengespeichert, und die in den Helfern verwendeten Manifestnamen werden geändert, um den MD5-Hash einzuschließen.

Sprockets setzt auch den Cache-Control-HTTP-Header auf max-age = 31536000. Dies signalisiert allen Caches zwischen Ihrem Server und dem Client-Browser, dass dieser Inhalt (die bereitgestellte Datei) für 1 Jahr zwischengespeichert werden kann. Dies hat zur Folge, dass die Anzahl der Anforderungen für dieses Asset von Ihrem Server verringert wird. Das Asset hat eine gute Chance, sich im lokalen Browser-Cache oder in einem Zwischen-Cache zu befinden.

Dieser Modus benötigt mehr Speicher, ist schlechter als der Standardmodus und wird nicht empfohlen.

Außerdem ist der Vorkompilierungsschritt überhaupt kein Problem, wenn Sie Capistrano für Ihre Bereitstellungen verwenden. Es kümmert sich um Sie. Du rennst einfach

cap deploy

oder (abhängig von Ihrem Setup)

cap production deploy

und du bist fertig. Wenn Sie es immer noch nicht verwenden, empfehle ich dringend, es auszuprobieren.

Sergio Tulentsev
quelle
Denken Sie also, dass die Sprache des offiziellen Leitfadens mit mir übereinstimmt? Ich habe diesen Leitfaden gesehen. Ich bin mir nicht ganz sicher, ob er bedeutet, was ich oben vorschlage. Was denkst du? Das ist meine Frage.
Jrochkind
Ja, Sie sagen im Grunde das Gleiche. Ich schlage vor, dass Sie die Live-Kompilierung nicht aktivieren.
Sergio Tulentsev